范围如何在for循环中起作用?

时间:2018-05-25 00:13:07

标签: javascript scope

当我在循环中创建5个按钮并单击i的值总是6



function createButtons() {
   for (var i = 1; i <= 5; i++) {
     var body = document.getElementsByTagName("BODY")[0];
     var button = document.createElement("BUTTON");
     button.innerHTML = 'Button ' + i;
     (function(num) {
       button.onclick = function() {
          alert('This is button ' + num);
       }
     })(i);
     body.appendChild(button);
   }
}
&#13;
&#13;
&#13;

但是当我将i的范围更改为阻止范围(使用IIFE或let关键字)时,它给出了正确的i值。它是如何在javascript引擎下工作的?

1 个答案:

答案 0 :(得分:0)

我已将您的功能分为incorrectcorrect一个。

incorrect版本就是您所要求的。 correct版本是您已经想到的,但不知道它为什么会起作用。

在错误的版本中,i的值将始终更新为最新值,因为i属于createButtons函数,并与所有onclick共享处理程序,它随着循环而改变。

在正确的版本中,i的值会以num的形式提供给IIFE,而num属于IIFE,而不属于createButtons

因此,num是固定的,因为为每个循环创建了一个新的num,因此不会与另一个onclick处理程序共享。

为什么呢?这是闭包在JavaScript中的工作方式。

Read this for deeper understanding on JavaScript closure.

function createButtons_incorrect() {
   for (var i = 1; i <= 5; i++) {
     var body = document.getElementsByTagName("BODY")[0];
     var button = document.createElement("BUTTON");
     button.innerHTML = 'Bad ' + i;
     button.onclick = function() {
        alert('This is button ' + i);
     }
     body.appendChild(button);
   }
}

function createButtons_correct() {
   for (var i = 1; i <= 5; i++) {
     var body = document.getElementsByTagName("BODY")[0];
     var button = document.createElement("BUTTON");
     button.innerHTML = 'Good ' + i;
     (function(num){
       button.onclick = function() {
          alert('This is button ' + num);
       }
     })(i);
     body.appendChild(button);
   }
}

createButtons_incorrect();
document.body.appendChild(document.createElement('br'));
createButtons_correct();