function first(){
var items = document.getElementsByTagName("li");
for(var x = 0; x < items.length; x++){
items[x].onclick = function() {
console.log(x);
}
}
}
function second(){
var items = document.getElementsByTagName("li");
for(var x = 0; x < items.length; x++){
(function(val) {
items[val].onclick = function() {
console.log(val);
}
})(x);
}
}
function third(){
var items = document.getElementsByTagName("li");
for(let x = 0; x < items.length; x++){
items[x].onclick = function() {
console.log(x);
}
}
}
列表中有4个元素。这3个函数的输出结果:
第一个函数:4 4 4 4
第二个函数:0 1 2 3
第三个函数:0 1 2 3
我无法理解第三个函数的输出。在第二个函数中,每次调用IIFE都会创建一个新的函数对象和一个新的val变量。但是在第三个函数中,变量x只有一个副本,那么如何得出输出结果:0 1 2 3。
如果我错了,请指出来。
let
的目的之一,它只在创建它的作用域中定义。items.length
个匿名函数都引用了不同实例的x
,因为你使用let
定义了它。 - Spencer Wieczorekfor
循环时,let
在闭包内“按预期工作”的事实是let
正常语义的一个例外,而不是其结果。const
也被限定在其块中,但我们不能做for (const a = i; a < n; a++)
- 这将在第二个循环迭代中引发错误,因为我们正在尝试为已经初始化的const
分配一个值。 - user1974458let
和const
都限定于包含它们的块级作用域,但是在for
循环中,let
还有一个特殊行为,将其限定于循环迭代而不是块级作用域。 - user1974458const
-每次迭代只有一个绑定循环变量(而不是每次迭代一个变量),这将无法回答OP的问题。 - user1974458let
作用域限定在块级别,而是作用域限定在迭代中。从技术上讲,迭代变量甚至没有在块中被定义;它是在循环结构中定义的,这些绑定的工作方式是基于具体情况而定的。个人认为let
和const
之间的不一致性令人惊讶和反直觉。我们不能使用const
来初始化for
循环的唯一原因是循环只有一个绑定。然后,如果我们使用let
,他们会给我们提供多个绑定! - user1974458