让关键字和关闭?

时间:2016-01-12 17:45:43

标签: javascript ecmascript-6

我正在学习ES6中的新功能。我有一个关于let的问题,它涉及这段代码:

for (let i = 0; i < 45; i++) {
    var div = document.createElement('div');
    div.onclick = function() {
        alert("you clicked on a box #" + i);
    };
    document.getElementsByTagName('section')[0].appendChild(div);
}

我对此代码感到困惑。在每个循环开始时声明的div对象发生了什么?这是一个全新的,单独的对象每次,不知何故被封闭在我的块范围内?或者这个div对象是否被覆盖,每次通过循环,如果是这样,它如何保持它与i的连接通过let给出?

3 个答案:

答案 0 :(得分:5)

当我想更好地了解ES6代码中发生的情况时,我将我的Javascript输入BabelJS REPL

输入REPL输出时的代码:

'use strict';

var _loop = function (i) {
  div = document.createElement('div');

  div.onclick = function () {
    alert("you clicked on a box #" + i);
  };

  document.getElementsByTagName('section')[0].appendChild(div);
};

for (var i = 0; i < 45; i++) {
  var div;

  _loop(i);
};

因为您使用let来分配i,所以它的值仅适用于每个循环迭代的循环范围(或Babel示例中的函数)。要获得div变量的相同功能,可以在循环体中分配该变量。

for (let div, i = 0; i < 45; i++) {
  div = document.createElement('div');
  ...
}

最后,关于闭包并保留i变量,您距离创建闭包只需一步,以保持每个i的当前div值。

// Create a function to hold on to a specific number
function createOnClick(index) {
  return function() {
    alert("you clicked on a box #", index);
  };
};

// Assign the function to the element's action 
div.onClick = createOnClick(i);

如果没有函数工厂,onClick值将始终获得最大i值44.这是因为函数在整个循环迭代后运行,i具有停在i < 45

答案 1 :(得分:2)

<div>在每次迭代中都是一个全新的对象,但不是包含在i的块范围内。

附加到div 的函数表达式但是也是一个全新的对象,但此对象 正在关闭i

答案 2 :(得分:0)

每次迭代div都是一个分支的新对象元素。 Let定义i只能在foreach循环(What's the difference between using "let" and "var" to declare a variable?)内访问。

一旦div元素被附加到“section”元素并且for循环开始一个新的迭代,你将丢失对最近附加的div的引用,用一个新的覆盖它。