Dalam pengantar sebelumnya, kita sudah tahu bahwa JavaScript tidak memiliki fungsi level blok, hanya ruang lingkup tingkat fungsi.
Salinan kode adalah sebagai berikut:
function test () {// SCOPE
untuk (var i = 0; i <10; i ++) {// bukan lingkup
// menghitung
}
console.log (i); // 10
}
Juga tidak ada namespace yang ditampilkan dalam JavaScript, yang berarti semuanya didefinisikan dalam ruang lingkup global. Setiap kali variabel dirujuk, JavaScript akan melintasi seluruh ruang lingkup global hingga ditemukan. Jika variabel masih belum ditemukan melalui ruang lingkup global penuh, kesalahan referensi di atas dilemparkan.
Harap masukkan deskripsi gambar
Variabel global implisit
Salinan kode adalah sebagai berikut:
// skrip a
foo = '42';
// skrip b
var foo = '42'
Dua contoh di atas memiliki efek yang berbeda. Yang pertama akan menentukan foo variabel dalam ruang lingkup global, sedangkan yang kedua akan menentukan variabel foo dalam ruang lingkup saat ini.
Kita harus mencatat bahwa jika Anda tidak menggunakan kata kunci VAR, itu akan memiliki dampak yang tidak terduga.
Salinan kode adalah sebagai berikut:
// ruang lingkup global
var foo = 42;
function test () {
// ruang lingkup lokal
foo = 21;
}
tes();
foo; // 21
Karena VAR tidak digunakan untuk mendefinisikan variabel FOO dalam uji fungsi, variabel global di luar fungsi akan ditimpa. Meskipun sepertinya bukan masalah besar, jika ada ribuan baris kode, itu akan menjadi bug yang sulit untuk dilacak.
Salinan kode adalah sebagai berikut:
// ruang lingkup global
var item = [/ * beberapa daftar */];
untuk (var i = 0; i <10; i ++) {
subloop ();
}
fungsi subloop () {
// ruang lingkup subloop
untuk (i = 0; i <10; i ++) {// Pernyataan var yang hilang
// Lakukan hal yang luar biasa!
}
}
Dalam contoh di atas, loop eksternal akan berhenti ketika eksekusi pertama dieksekusi, karena variabel I di dalam fungsi subloop akan mengesampingkan variabel global eksternal i. Kita hanya perlu menambahkan var di dalam fungsi untuk menghindari kesalahan ini, jadi kita tidak boleh lupa untuk menambahkan kata kunci var saat mendefinisikan variabel. Kecuali kita ingin berdampak pada variabel global eksternal.
Variabel lokal
Variabel lokal dalam JavaScript hanya dapat dihasilkan dalam dua cara, satu dinyatakan melalui kata kunci VAR, dan yang lainnya digunakan sebagai parameter formal fungsi.
Salinan kode adalah sebagai berikut:
// ruang lingkup global
var foo = 1;
var bar = 2;
var i = 2;
tes fungsi (i) {
// ruang lingkup lokal dari tes fungsi
i = 5;
var foo = 3;
bar = 4;
}
tes (10);
Pada saat ini, variabel I dan FOO di dalam uji fungsi adalah variabel lokal, dan batang akan mengesampingkan bilah variabel global eksternal.
Mengangkat
JavaScript akan mempromosikan deklarasi variabel, yang berarti bahwa kedua ekspresi VAR dan deklarasi fungsi akan dipromosikan ke bagian atas ruang lingkup.
Salinan kode adalah sebagai berikut:
batang();
var bar = function () {};
var somevalue = 42;
tes();
tes fungsi (data) {
if (false) {
goo = 1;
} kalau tidak {
var goo = 2;
}
untuk (var i = 0; i <100; i ++) {
var e = data [i];
}
}
Sebelum kode di atas dijalankan, deklarasi ekspresi var dan uji fungsi akan dipromosikan ke atas, sehingga program akan berjalan secara normal dan tidak akan melaporkan kesalahan.
Salinan kode adalah sebagai berikut:
// pernyataan var dipindahkan ke sini
var bar, somevalue; // default untuk 'tidak terdefinisi'
// Deklarasi fungsi juga dipindahkan
tes fungsi (data) {
Var Goo, I, E; // Lingkungan blok yang hilang memindahkannya di sini
if (false) {
goo = 1;
} kalau tidak {
goo = 2;
}
untuk (i = 0; i <100; i ++) {
E = data [i];
}
}
batang(); // gagal dengan typeError karena bilah masih 'tidak ditentukan'
Somevalue = 42; // penugasan tidak terpengaruh oleh pengangkat
bar = function () {};
tes();
Karena JavaScript tidak memiliki ruang lingkup level blok, ini tidak hanya akan meningkatkan ekspresi VAR, tetapi juga membuat struktur IF kurang intuitif.
Dalam contoh di atas, meskipun tampaknya jika beroperasi pada variabel global goo, pada kenyataannya, karena variabel goo dipromosikan, variabel lokal dimodifikasi.
Jika Anda tidak memiliki pemahaman tentang aturan elevasi, Anda mungkin berpikir bahwa kode berikut akan melempar kesalahan referensi.
Salinan kode adalah sebagai berikut:
// periksa apakah beberapa impor yang telah diinisialisasi
if (! someimportantthing) {
var someimportanting = {};
}
Tentu saja, kode di atas tidak salah, karena ekspresi VAR telah dipromosikan ke atas sebelum kode dijalankan.
Salinan kode adalah sebagai berikut:
var beberapa impor;
// Kode lain mungkin menginisialisasi sesuatu yang penting di sini, atau tidak
// Pastikan itu ada di sana
if (! someimportantthing) {
Someimportanting = {};
}
Di sini saya ingin merekomendasikan posting blog @Nightire Fan GE "Memahami JavaScript (II)", yang menjelaskan peningkatan dengan sangat teliti.
Urutan Resolusi Nama
Saat mencoba mengakses variabel FOO dalam ruang lingkup fungsi, JavaScript akan mencarinya dalam urutan berikut:
Apakah ada definisi var foo dalam ruang lingkup saat ini.
Apakah ada variabel foo dalam parameter fungsi.
Apakah fungsinya itu sendiri foo.
Lompat ke domain definisi luar dan mulai melihat ke atas dari bagian pertama.
Namespace
Salah satu masalah yang paling umum adalah penamaan konflik, karena JavaScript hanya memiliki satu ruang lingkup global. Tetapi masalah ini dapat diselesaikan dengan fungsi eksternal anonim.
Salinan kode adalah sebagai berikut:
(fungsi() {
// A mandiri "namespace"
window.foo = function () {
// penutupan yang terbuka
};
}) (); // Jalankan fungsi segera
Fungsi anonim dalam contoh di atas dianggap sebagai ekspresi, sehingga mereka dieksekusi.
Salinan kode adalah sebagai berikut:
(// mengevaluasi fungsi di dalam orang tua
fungsi() {}
) // dan kembalikan objek fungsi
() // Panggil hasil evaluasi
Tentu saja, kita juga dapat menggunakan metode lain untuk memanggil ekspresi fungsi, struktur yang berbeda, tetapi efek yang sama.
Salinan kode adalah sebagai berikut:
// Beberapa gaya lain untuk secara langsung memohon
!fungsi(){}()
+function () {} ()
(fungsi(){}());
// dan sebagainya ...
Meringkaskan
Dianjurkan agar Anda menggunakan fungsi eksternal anonim untuk merangkum kode ke dalam ruang, yang tidak hanya menyelesaikan konflik namespace, tetapi juga memfasilitasi modularisasi program.
Selain itu, menggunakan variabel global bukanlah kebiasaan yang baik, yang akan membawa biaya perawatan yang tinggi dan rentan terhadap kesalahan.
Namespaces memiliki jenis, fungsi, variabel, templat, dll., Semuanya milik entitas.
Kesamaan utama suatu entitas adalah bahwa ia dapat memiliki nama. (Selain itu, tag juga dapat memiliki nama, tetapi itu bukan entitas.)
Namespace Scope adalah istilah umum dalam ruang lingkup, yang sejajar dengan cakupan memblokir, ruang lingkup kelas, lingkup prototipe fungsi, dan ruang lingkup fungsi (hanya valid untuk label). Nama -nama yang dinyatakan dalam namespace ada di ruang lingkup namespace. Nama global dipertimbangkan dalam ruang lingkup namespace global implisit.
Fungsi namespace memang lingkup, tetapi berbeda dari ruang lingkup sederhana. Anda dapat mendeklarasikan namespace yang sama di beberapa tempat dalam beberapa kali, tetapi konten di dalam tidak dapat didefinisikan ulang. Mereka pada akhirnya akan mensintesis namespace, seperti halnya STD, definisi makro di mana -mana.