Baru -baru ini, saya membaca ulang "JavaScript Advanced Programming 3" dan merasa bahwa saya harus menulis beberapa blog untuk merekam beberapa pengetahuan yang saya pelajari, kalau tidak saya akan melupakannya. Yang ingin saya ringkas hari ini adalah lingkungan dan ruang lingkup eksekusi JS.
Pertama, mari kita bicara tentang lingkungan eksekusi
1. Lingkungan Eksekusi
Konsep dalam buku ini, lingkungan eksekusi mendefinisikan data lain yang memiliki variabel atau fungsi yang memiliki akses ke, dan menentukan perilaku masing -masing. Setiap lingkungan eksekusi memiliki objek variabel yang terkait dengannya. Semua variabel dan fungsi yang ditentukan dalam lingkungan disimpan dalam objek ini. Meskipun kami tidak dapat mengakses objek ini saat menulis kode, parser akan menggunakannya di latar belakang saat memproses data.
Lingkungan eksekusi adalah konsep, mekanisme yang mendefinisikan apakah suatu variabel atau fungsi memiliki izin untuk mengakses data lain
Dalam JavaScript, kode JavaScript yang dapat dieksekusi dibagi menjadi tiga jenis:
1. Kode global, yaitu kode global yang tidak ada dalam fungsi apa pun, seperti: file JS, kode JS yang tertanam di halaman HTML, dll.
2. Kode evaluasi, yaitu kode JS yang dieksekusi secara dinamis menggunakan fungsi eval ().
3. Kode fungsi, yaitu, kode fungsi JS body dalam fungsi yang ditentukan pengguna.
Lewati kode eval dan hanya berbicara tentang lingkungan eksekusi global dan lingkungan eksekusi fungsi.
1. Lingkungan Global:
Lingkungan global adalah lingkungan eksekusi yang paling periferal. Lingkungan eksekusi global dianggap sebagai objek jendela. Oleh karena itu, semua variabel dan fungsi global dibuat sebagai properti dan metode objek jendela. Ketika kode dimuat ke dalam browser, lingkungan eksekusi global dibuat (lingkungan eksekusi global hanya dihancurkan ketika kita menutup halaman web atau browser). Misalnya, di halaman, buat lingkungan eksekusi global ketika kode JS dimuat untuk pertama kalinya.
Ini juga mengapa penutupan memiliki kerugian kebocoran memori. Karena fungsi eksternal dalam penutupan diperlakukan sebagai lingkungan global. Jadi itu tidak akan dihancurkan dan akan disimpan dalam ingatan.
2. Lingkungan Eksekusi Fungsi
Setiap fungsi memiliki lingkungan eksekusi sendiri. Saat eksekusi memasuki suatu fungsi, lingkungan eksekusi fungsi akan didorong ke bagian atas tumpukan lingkungan eksekusi dan mendapatkan hak eksekusi. Ketika fungsi ini dijalankan, lingkungan eksekusi dihapus dari atas tumpukan dan hak eksekusi dikembalikan ke lingkungan eksekusi sebelumnya. Ini adalah aliran eksekusi dalam program ecmascript.
Ini juga dapat ditafsirkan dengan cara ini: ketika fungsi JavaScript disebut, fungsi akan memasuki lingkungan eksekusi yang sesuai dengan fungsi. Jika fungsi lain dipanggil, lingkungan eksekusi baru dibuat, dan proses eksekusi berada di lingkungan itu selama panggilan fungsi. Ketika fungsi yang dipanggil kembali, proses eksekusi kembali ke lingkungan eksekusi asli. Oleh karena itu, menjalankan kode JavaScript membentuk tumpukan lingkungan eksekusi.
Ketika suatu fungsi dipanggil, lingkungan lokal dari fungsi dibuat (setelah kode dalam fungsi dieksekusi, lingkungan dihancurkan, dan semua variabel dan definisi fungsi yang disimpan di dalamnya juga dihancurkan).
2-1 periode definisi
Ketika suatu fungsi didefinisikan, atribut [SCOPE]] akan dibuat. Objek ini sesuai dengan daftar objek. Objek dalam daftar hanya dapat diakses secara internal oleh JavaScript dan tidak dapat diakses melalui sintaks.
(Lingkup berarti ruang lingkup.)
Kami mendefinisikan fungsi global A, dan kemudian fungsi A membuat atribut A [[Lingkup]] A. Pada saat ini, [[Lingkup]] hanya berisi objek global [objek global].
Jika kita mendefinisikan fungsi B di dalam A, maka fungsi B juga akan membuat atribut A [SCOPE]]. Atribut B's [[SCOPE]] berisi dua objek, satu adalah objek aktif objek aktivasi aktivasi aktif ACTIF A dan yang lainnya adalah objek global. Objek aktif A ada di depan dan objek global ada di belakang.
Singkatnya, urutan daftar objek dalam properti [lingkup] fungsi adalah objek aktivasi dari lapisan fungsi sebelumnya, dan kemudian lapisan atas, sampai ke objek global terluar.
Inilah kode sampel: A hanya memiliki satu ruang lingkup, B memiliki dua lingkup
// fungsi fungsi eksternal a () {var somevar; // fungsi fungsi dalam b () {var somevar; }}2-2 periode eksekusi
Ketika suatu fungsi dieksekusi, ia memasuki lingkungan eksekusi fungsi. Pertama, ia menciptakan objek aktifnya sendiri [objek aktivasi] (objek ini berisi definisi ini, argumen, variabel lokal (termasuk parameter yang disebutkan) dan rantai ruang lingkup objek variabel. Kemudian, salin ruang lingkup lingkungan eksekusi ke dalam [rantai lingkup] dalam rantai yang ada, dan akhirnya mendorong objek aktif ke bagian atas rantai [scope rantai]]. dan objek yang memiliki izin untuk mengakses lingkungan eksekusi.
// Langkah pertama adalah menciptakan lingkungan eksekusi global. Konteks eksekusi global dan objek aktivitas global. // Tentukan global [[Lingkup]], yang hanya berisi objek jendela // Pindai variabel definisi global dan objek fungsi: warna 【tidak terdefinisi】, ChangeColor 【FD membuat changeColor [[ruang lingkup]], yang hanya berisi objek aktivitas global], yang ditambahkan ke jendela, sehingga variabel global dan objek fungsi global adalah objek fungsi global adalah objek fungsi global adalah objek fungsi global. // Program telah didefinisikan sehingga ChangeColor () dapat dieksekusi di mana saja di lingkungan eksekusi ini. The color has also been defined, but its value is undefined// The second step is color assigning "blue"var color = "blue";// It does not require assignment, it refers to its own function changecolor() { // The fourth step enters the execution environment of changecolor// Copy the changecolor [[scope]] to the scope chain // Create active objects, scan to define variables and define functions, OtherColor 【tidak terdefinisi】 dan swapcolors 【fd membuat swapcolors [[ruang lingkup]] dan menambahkan objek aktif dan objek aktif global】 ke objek aktif, dan juga menambahkan argumen dan ini // objek aktif mendorong rantai lingkup top // program ini telah ditentukan sehingga swapcolors () dapat dieksekusi di mana saja di mana saja di mana saja. Lainnya warna telah didefinisikan, tetapi nilainya tidak terdefinisi // penugasan kelima lainnya "merah" var laincolor = "merah"; // Ini tidak memerlukan penugasan, itu mengacu pada fungsinya sendiri swapcolors () {// Langkah 7 Masukkan lingkungan eksekusi swapcolors dan buat objek aktif // salin swapcolors '[scope]] ke rantai ruang lingkup // scan untuk menentukan variabel dan mendefinisikan objek fungsi ini, menambah variabel tempcolor 【【【【【【【【【【【【【【【【【 Nilai penugasan Tempcolor dari Color lain, warna lain dan warna akan ditemukan di sepanjang rantai lingkup, dan terus mengeksekusi var Tempcolor = lainColor; OtherColor = warna; warna = tempcolor; } // Langkah 6: Jalankan SwapColors dan masukkan lingkungan eksekusi swapcolors ();} // Langkah 3: Eksekusi ChangeColor dan masukkan lingkungan eksekusi ChangeColor ();2-3 Access Identifier:
Ketika pengidentifikasi ditemui selama eksekusi kode JS, ia akan mencari dalam rantai ruang lingkup konteks eksekusi (konteks eksekusi) berdasarkan nama pengidentifikasi. Mulai dari objek pertama rantai lingkup (objek objek aktivasi fungsi), jika tidak ditemukan, cari objek berikutnya dalam rantai lingkup, dan ulangi sampai definisi pengidentifikasi ditemukan. Jika objek terakhir dalam ruang lingkup tidak ditemukan setelah mencari pencarian, yaitu, objek global (objek global), kesalahan akan dilemparkan, mendorong tidak ditentukan.
2. Rantai Lingkup/Lingkungan (Rantai Lingkup/Lingkungan)
Ketika kode dieksekusi di lingkungan, rantai lingkup dibuat. Tujuan dari rantai ruang lingkup adalah untuk memastikan akses tertib ke semua variabel dan fungsi yang memiliki izin untuk mengakses lingkungan eksekusi. Seluruh rantai ruang lingkup adalah daftar tertaut yang dibangun oleh objek variabel di lokasi eksekusi yang berbeda sesuai dengan aturan. Ujung depan rantai ruang lingkup selalu merupakan objek variabel di lingkungan di mana kode yang saat ini sedang dieksekusi berada.
Jika lingkungan ini adalah fungsi, objek aktivasi digunakan sebagai objek variabel. Objek aktif hanya berisi satu variabel di awal, yang merupakan objek argumen di dalam fungsi. Objek variabel berikutnya dalam rantai lingkup berasal dari lingkungan inklusi fungsi, dan objek variabel berikutnya berasal dari lingkungan inklusi berikutnya. Dengan cara ini, ia berlanjut ke lingkungan eksekusi global, dan objek variabel dari lingkungan eksekusi global selalu menjadi objek terakhir dalam rantai ruang lingkup.
Seperti yang ditunjukkan pada gambar:
Contoh dalam buku:
var warna = "biru"; function changeColor () {var OtherColor = "Red"; fungsi swapcolors () {var tempcolor = lainColor; OtherColor = warna; warna = tempcolor; // todo sesuatu} swapcolors ();} changeColor (); // Tempcolor dan Anocolor tidak dapat diakses di sini; tetapi warna dapat diakses; waspada ("warna sekarang"+warna);Melalui analisis di atas, kita dapat mengetahui bahwa lingkungan internal dapat mengakses semua lingkungan eksternal melalui rantai lingkup, tetapi lingkungan eksternal tidak dapat mengakses variabel dan fungsi apa pun di lingkungan internal.
Lingkungan ini linier dan tertib. Setiap lingkungan dapat mencari rantai ruang lingkup ke atas ke variabel permintaan dan nama fungsi; Namun, lingkungan apa pun tidak dapat memasuki lingkungan eksekusi lain dengan mencari rantai ruang lingkup ke bawah.
Untuk fungsi swapcolor () dalam contoh di atas, rantai lingkupnya meliputi: objek variabel swapcolor (), objek variabel changeColor (), dan objek global. Lingkungan lokal SwapColor () mulai mencari variabel dan nama fungsi dalam objek variabelnya sendiri. Jika tidak dapat ditemukan, cari rantai ruang lingkup Changecolor ke atas. . . . . Dan sebagainya. Namun, fungsi changeColor () tidak dapat mengakses variabel di swapcolor
Wahyu: Cobalah menggunakan variabel lokal untuk mengurangi waktu pencarian
1. Tidak ada ruang lingkup level blok
Tidak seperti C, C ++, dan Java, JavaScript tidak memiliki ruang lingkup tingkat blok. Lihat kode berikut:
if (true) {var myvar = "zhang san"; } peringatan (myvar); // zhang sanJika ada ruang lingkup level blok, MyVar tidak dapat diakses dari luar. Lihatlah yang berikut ini
untuk (var i = 0; i <10; i ++) {console.log (i)} alert (i); // 10Untuk bahasa dengan ruang lingkup tingkat blok, seperti kode Java atau C#, saya adalah variabel yang diinisialisasi, dan tidak dapat diakses di luar. Karena saya hanya ada dalam berat loop, setelah menjalankan loop untuk, semua variabel di FOR dihancurkan. Ini tidak terjadi di JavaScript. Deklarasi variabel untuk akan ditambahkan ke lingkungan eksekusi saat ini (di sini adalah lingkungan eksekusi global). Oleh karena itu, setelah loop FOR selesai, variabel saya masih ada di lingkungan eksekusi di luar loop. Oleh karena itu, 10 akan menjadi output.
2. Deklarasikan variabel
Ketika suatu variabel dideklarasikan menggunakan VAR, variabel ini akan ditambahkan secara otomatis ke lingkungan terdekat yang tersedia. Untuk bagian dalam suatu fungsi, lingkungan terdekat adalah variabel lokal dari fungsi. Jika variabel tidak diinisialisasi, variabel secara otomatis ditambahkan ke fungsi global.
Kodenya adalah sebagai berikut:
var name = "xiao ming"; function getName () {alert (name); // 'tidak terdefinisi' var name = 'xiao huang'; peringatan (nama); // xiao huang} getName ()Mengapa nama depan tidak ditentukan? Ini karena, parser JavaScript memasuki lingkungan eksekusi fungsi dan memindai var dan fungsi terlebih dahulu.
Ini setara dengan mempromosikan Deklarasi VAR atau Fungsi [Deklarasi Fungsi] ke bagian atas lingkungan eksekusi.
Dengan kata lain, saat memasuki fungsi GetName kami, mekanisme pencarian pengidentifikasi menemukan VAR, dan namanya adalah nama variabel lokal, bukan nama global, karena nama dalam fungsi dipromosikan ke atas.
Kode di atas akan diuraikan sebagai berikut:
var name = "xiao ming"; function getName () {var name; peringatan (nama); // 'tidak terdefinisi' var name = 'xiao huang'; peringatan (nama); // xiao huang} getName ()Perpanjang rantai ruang lingkup:
Meskipun hanya ada dua jenis lingkungan eksekusi - ruang lingkup global dan ruang lingkup fungsional, rantai ruang lingkup masih dapat diperluas dalam beberapa cara. Karena beberapa pernyataan dapat menambahkan objek variabel sementara ke bagian atas rantai lingkup.
Ada dua situasi di mana ini terjadi:
1. Blok tangkapan dari pernyataan mencoba-tangkapan;
2. Dengan pernyataan;
Di atas adalah semua tentang artikel ini. Saya berharap akan sangat membantu bagi semua orang untuk belajar dan memahami lingkungan dan ruang lingkup eksekusi JavaScript.