JavaScript 闭包:通过示例理解 let 和 var 的区别
JavaScript 闭包:通过示例理解 let 和 var 的区别
这个问题已经有了答案:
虽然我理解let
允许您声明仅限于块级别的范围的变量,但在使用它与javascript闭包时,我遇到了一个奇怪的let
和var
之间的区别。下面是我的例子:
使用let
:
function buildFunction() { var arr = []; for(var i = 0; i < 3; i++) { let j = i; //Using let to assign j arr.push( function(){ console.log(j); } ) } return arr; } var fs = buildFunction(); fs[0](); fs[1](); fs[2]();
上面的代码片段输出:
0 1 2
使用var
:
function buildFunction() { var arr = []; for(var i = 0; i < 3; i++) { var j = i; //Using var to assign j arr.push( function(){ console.log(j); } ) } return arr; } var fs = buildFunction(); fs[0](); fs[1](); fs[2]();
上面的代码片段输出以下内容:
2 2 2
我的问题是:
- 如果我在块内部使用
var
并在执行期间为其赋值,那么它不应该像let
一样正常工作并在内存中存储不同的j的副本吗? - javascript是否在闭包中以不同的方式处理
let
和var
?
对此的任何澄清将不胜感激。
admin 更改状态以发布 2023年5月23日
var
将作用域限制在函数内;let
将作用域限制在代码块内。
在你的例子中,使用var时,j
的作用域限制在函数buildFunction()
内。这意味着你在每个函数中都在使用 '相同的' j
。当你的for循环运行时,j被设置为0,然后是1,再然后是2。当你运行控制台日志时,引用的是被设置为2的j,因此你得到的是2 2 2
。
当你使用let
时,你将j
的作用域限制在for循环的每次迭代中。这意味着每次迭代都有一个 '不同的' j
,而控制台日志打印的是你期望打印出的内容。
如果你使用ES5并且需要使用var,你可以通过将原始的匿名函数封装在一个自执行函数中并将j
作为参数传入来复制let的效果(让它打印0 1 2
)。 这将在自执行函数中为j
创建一个新的作用域,其值为当前迭代中j
的值。
function buildFunction() { var arr = []; for(var i = 0; i < 3; i++) { var j = i; //Using var to assign j arr.push( //self executing function (function(j) { //j here is scoped to the self executing function and has the value of j when it was called in the loop. Any changes to j here will not affect the j scope outside this function, and any changes to j outside this function will not affect the j scoped inside this function. //original function return function() { console.log(j); } })(j) //call with the value of j in this iteration ) } return arr; } var fs = buildFunction(); fs[0](); fs[1](); fs[2]();