Closure(让关键字) - Javascript

时间:2017-03-02 13:31:58

标签: javascript ecmascript-6 closures

const

列表中有4个元素。 3个函数的输出:

第一名:4 4 4 4
第二名:0 1 2 3
第三名:0 1 2 3

我无法理解第三个函数的输出。在第二个函数中,每次调用IIFE都会创建一个新的函数对象,从而创建一个新的val变量。但是在第三个函数中,有一个变量x的副本,那么输出如何:0 1 2 3

如果我错了,请纠正我。

3 个答案:

答案 0 :(得分:4)

在MDN的let文档中,他们在Cleaner Code in inner functions部分提供了一个涵盖此确切案例的示例:

for (let i = 1; i <= 5; i++) {
  let item = document.createElement('li');
  item.appendChild(document.createTextNode('Item ' + i));

  item.onclick = function(ev) {
    console.log('Item ' + i + ' is clicked.');
  };
  list.appendChild(item);
}
  

上面的示例按预期工作,因为(匿名)内部函数的五个实例引用变量i的五个不同实例。注意,如果用var替换let,它就不会按预期工作,因为所有内部函数都将返回i的相同最终值:6。此外,我们可以通过移动创建的代码来保持环路清理范围将新元素纳入每个循环的范围。

同样适用于您的情况,因为您使用let每个匿名函数引用x的不同实例。循环的每次迭代都有不同的实例。发生这种情况是因为let具有块级范围而不是var具有的全局函数范围。

答案 1 :(得分:1)

这是let关键字最棘手的例子之一。

Let将变量绑定到块(&amp;在本例中为for循环)这一事实意味着它将变量绑定到循环的每次迭代。因此,当循环结束时,您有4个项目(项目[0]到项目[3]的项目)听取点击事件。

实际上for-loop中的third function会产生以下结果:

items[0].onclick = function() {
        console.log(0);
   }
items[1].onclick = function() {
        console.log(1);
   }
items[2].onclick = function() {
        console.log(2);
   }
items[3].onclick = function() {
        console.log(3);
   }

请务必详细了解Let here in MDN其他一些令人兴奋的案例。

答案 2 :(得分:0)

来自文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

  

允许您声明范围有限的变量   使用它的块,语句或表达式。这与此不同   var关键字,它全局定义变量,或者本地定义变量   整个函数,无论块范围如何。

当它是var时,它会像所有变量一样被提升。

如果让范围是它所定义的块。