简体   繁体   中英

let keyword and closures?

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM