最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - let keyword and closures? - Stack Overflow

programmeradmin5浏览0评论

I am learning about the new features in ES6. I have a question about let and it concerns this code:

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);
}

I am confused by this code. What is happening with that div object that is declared at the start of each loop? Is that a brand new, separate object each time, somehow enclosed in the block scope of i? Or is this div object being overwritten each pass through the loop and if so, how does it maintain it's connection to the i it is given via let?

I am learning about the new features in ES6. I have a question about let and it concerns this code:

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);
}

I am confused by this code. What is happening with that div object that is declared at the start of each loop? Is that a brand new, separate object each time, somehow enclosed in the block scope of i? Or is this div object being overwritten each pass through the loop and if so, how does it maintain it's connection to the i it is given via let?

Share Improve this question asked Jan 12, 2016 at 17:45 user4853user4853 3633 silver badges8 bronze badges 1
  • The onclick function is a closure that closes over i. The div has nothing to do with that. – Bergi Commented Jan 12, 2016 at 17:55
Add a ment  | 

3 Answers 3

Reset to default 5

When I like to get a better understanding of what's happening in ES6 code, I enter my Javascript into the BabelJS REPL.

Your code when entered into the REPL outputs:

'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);
};

Because you used let to assign i, its value is only available in the scope of the loop (or the function in the Babel example) for each loop iteration. To get the same functionality for the div variable, you could assign that variable in the loop body.

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

Lastly, about closures and holding on to the i variable, you're one step away from creating a closure to maintain the current i value for each 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);

Without the function factory, the onClick value would always get the maximum i value of 44. This is because the function is being run after the entire loop has iterated and i has stopped at i < 45.

The <div> is a brand new object in each iteration, but it isn't enclosed in the block scope of i.

The function expression that is attached to the div is however also a brand new object, but this object is closing over i.

On each iteration div is a branch new object element. Let defines i to be accessible only within foreach loop (What's the difference between using "let" and "var" to declare a variable?).

Once the div element is appended to "section" element and for loop starts a new iteration, you lose a reference to recently appended div by overriding it with a new one.

发布评论

评论列表(0)

  1. 暂无评论