Rumah > Artikel > hujung hadapan web > Fahami secara ringkas var dan biarkan dalam pembolehubah atau gelung JavaScript
Artikel ini membawakan anda pengetahuan yang berkaitan tentang javascript terutamanya memperkenalkan penjelasan terperinci var dan biarkan dalam pembolehubah atau gelung JavaScript. Artikel ini memperkenalkan kandungan secara terperinci di sekitar tema, yang mempunyai kepentingan tertentu. Untuk nilai rujukan, mari kita lihat di bawah ini saya harap ia akan membantu semua orang.
[Cadangan berkaitan: tutorial video javascript, bahagian hadapan web]
// 一道经典面试题: var funcs = []; for (var i = 0; i < 3; i++) { funcs[i] = function() { console.log("My value: " + i) }; } for (var j = 0; j < 3; j++) { funcs[j](); } /* 输出结果: > My value: 3 > My value: 3 > My value: 3 */
Sebab mengapa fenomena ini berlaku ialah:
Penyelesaian dalam era ES5 adalah untuk mencipta penutupan melalui IIFE, menyimpan pembolehubah dalam badan fungsi, dan kemudian melaksanakan fungsi Pembolehubah var luar tidak akan diakses.
var funcs = []; for (var i = 0; i < 3; i++) { // 1. 闭包 funcs[i] = (function (i) { return function () { console.log("My value: " + i); }; })(i); } for (var j = 0; j < 3; j++) { funcs[j](); }
Pengisytiharan biarkan ialah skop peringkat blok dan pembolehubah dalam badan gelung tidak akan dibocorkan di luar penyataan blok.
Oleh itu, apabila mengakses pembolehubah i selepas gelung tamat, tiada gangguan daripada pembolehubah skop luar, dan apa yang diakses secara semula jadi adalah nilai pembolehubah yang disimpan dalam badan fungsi.
var funcs = []; // 2. let for (let i = 0; i < 3; i++) { funcs[i] = function() { console.log("My value: " + i); }; } for (var j = 0; j < 3; j++) { funcs[j](); }
Ia juga boleh dilihat dari sini bahawa menggunakan var untuk memulakan gelung for itu sendiri adalah berlawanan dengan intuisi.
Pembolehubah yang digunakan untuk memulakan gelung for hendaklah pembolehubah setempat bagi gelung for ini seharusnya tidak bermakna selepas gelung berakhir.
Tetapi jika anda menggunakan var untuk memulakan, memandangkan skop pembolehubah yang diisytiharkan oleh var ialah skop fungsi, pembolehubah permulaan ini berada dalam skop yang sama seperti gelung for dan tidak dihadkan oleh gelung for.
Ia mestilah pembolehubah tempatan bagi gelung for, tetapi ia didedahkan dalam skop lapisan yang sama seperti gelung for, dan nilai pembolehubah telah diubah mengikut bilangan gelung, yang secara semula jadi akan mempengaruhi akses pembolehubah oleh kod lain selepas gelung berakhir.
Jika anda menggunakan let untuk memulakan gelung for, anda tidak akan menghadapi masalah ini, kerana skop yang diisytiharkan oleh let ialah skop peringkat blok, dan pembolehubah permulaan ini akan menjadi pembolehubah setempat bagi gelung for sebagai dijangka.
Kesimpulan pertama:
Lihat pertama pada kesimpulan pertama, Spesifikasi mengatakan ini:
Yes It boleh dilihat bahawa spesifikasi tidak mempunyai sebarang rawatan khas untuk pembolehubah permulaan var, jadi ia boleh digunakan secara langsung. Pada masa ini, pembolehubah ialah pembolehubah var biasa dan berada dalam skop yang sama dengan gelung for.
Mari kita gunakan kod untuk membuktikannya:
var funcs = []; for (var i = 0; i < 3; i++) { // !!!重复声明了一个同名的var变量 var i = 5; console.log("My value: " + i); } /* 只会输出一次: > My value: 5 */
var boleh diisytiharkan berulang kali dan nilai akan ditimpa, jadi isytiharkan satu lagi var i = 5
dalam badan gelung , pembolehubah gelung dimusnahkan, dan gelung for akan dilonjak keluar terus.
var funcs = []; for (var i = 0; i < 3; i++) { // 用let声明了一个和循环变量同名的变量 let i = 5; console.log("My value: " + i); } /* 一共输出了3次: > My value: 5 > My value: 5 > My value: 5 */
Mulakan pembolehubah var dalam skop fungsi, dan pembolehubah let dalam badan gelung berada dalam skop blok Pembolehubah let dalam badan gelung mempunyai keutamaan untuk mengakses pembolehubah biarkan dalam skop blok , jadi nilai i dalam badan gelung akan ditimpa.
Dan kerana pembolehubah var sebenarnya berada dalam skop luar pemboleh ubah let, pemboleh ubah let tidak diisytiharkan berulang kali dan tiada ralat dilaporkan, pembolehubah var juga akan menyelesaikan misinya sebagai pembolehubah gelung seperti yang dijadualkan.
Mari kita lihat kesimpulan kedua, juga melihat spesifikasi dahulu:
Jelas sekali bahawa menggunakan let untuk memulakan akan mempunyai satu panggilan lebih daripada menggunakan var perIterationLets
sesuatu. Apakah itu
perIterationLets
?
Seperti yang dapat dilihat dari spesifikasi, perIterationLets
berasal dari LexicalDeclaration(词法声明)
dalam boundNames
.
Dan ini LexicalDeclaration(词法声明)
sebenarnya adalah kenyataan let yang kami gunakan untuk memulakan.
Boleh difahami bahawa jika kita menggunakan pernyataan let untuk memulakan gelung for, pembolehubah let tidak akan digunakan terus di dalam gelung for seperti pembolehubah var Sebaliknya, pembolehubah let akan dikumpul terlebih dahulu digunakan dalam beberapa cara. Borang ditukar kepada perIterationLets
dan kemudian dihantar ke badan gelung.
Untuk apa perIterationLets
digunakan?
sebagai parameter sebagai perIterationLets
, iaitu badan gelung. ForBodyEvaluation
hanya melakukan satu perkara, iaitu, sebagai parameter perIterationLets
: CreatePerIterationEnvironment
从字面上理解,CreatePerIterationEnvironment
意思就是每次循环都要创建的环境。
要注意,这个环境不是{...}
里的那些执行语句所处的环境。 {...}
里的执行语句是statement
,在规范里可以看到,stmt
有自己的事情要做。
这个环境是属于圆括号的作用域,也就是我们定义的let初始化变量所在的作用域。
再看看每次循环都要创建的环境被用来干嘛了:
逐步分析一下方法:CreatePerIterationEnvironment
这个
lastIterationEnv(上一次循环时的环境)
;lastIterationEnv
同级的新作用域,作为thisIterationEnv(本次循环的环境)
;perIterationLets
,在thisIterationEnv(本次循环的环境)
里创建一个同名的可变绑定,找到它们在lastIterationEnv(上一次循环时的环境)
里的终值,作为这个同名绑定的初始值;thisIterationEnv(本次循环的环境)
交还给执行上下文。简而言之就是,for循环会在迭代之前创建一个和初始化变量同名的变量,并使用之前迭代的终值将这个变量初始化以后,再交还给执行上下文。
用伪代码理解一下这个过程就是:
到这里又有一个问题,既然把圆括号内的变量向循环体里传递了,那如果在循环体里又重复声明了一个同名变量,算不算重复声明,会不会报错?
答案是不会。
因为CreatePerIterationEnvironment
在执行时,在新环境里创建的是一个可变的绑定,因此如果在循环体内重复声明一个名字为i
的变量,只是会影响循环体内执行语句对i
值的访问。
var funcs = []; for (let i = 0; i < 3; i++) { // !!!用let声明了一个和循环变量同名的变量 let i = 5; console.log("My value: " + i); } /* 一共输出了3次: > My value: 5 > My value: 5 > My value: 5 */
在for循环中使用var声明来初始化的话,循环变量会暴露在和for循环同一作用域下,导致循环结束后还能访问到循环变量,且访问到的变量值是经过循环迭代后的值。
解决这个问题的方法如下:
for循环是怎么处理用let和var声明的初始化变量的?
【相关推荐:javascript视频教程、web前端】
Atas ialah kandungan terperinci Fahami secara ringkas var dan biarkan dalam pembolehubah atau gelung JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!