不确定我是否完全理解Javascript中的变量作用域

Not sure I quite understand variable scope in Javascript

本文关键字:Javascript 变量 作用域 是否 不确定      更新时间:2023-09-26

如果这看起来有点容易,很抱歉。我对Javascript还是比较陌生的。

我正在生成一个复选框列表。在复选框的上单击,我想让它弹出关联的文本。即,名为"one"的复选框应显示"one"。在我的示例中,它只显示"两个"。

但是,click()回调方法只调用最后添加的复选框的文本。此处的"v"变量是否未按复选框分配?看起来"v"的行为就像一个全局变量。

this.view = document.createElement("div");
var tbody = document.createElement("tbody");
var popupValues = {"A", "B"};
for (var i=0;i<this.popupValues.length;i++) {
    var v = popupValues[i];
    var tr  = document.createElement('tr');
    var tdCheck  = document.createElement('td');
    var ChkBx = document.createElement('input')
    ChkBx.type = 'checkbox';
    tdCheck.appendChild(ChkBx);
    var self = this;
    $(ChkBx).live('change', function(){
        if($(this).is(':checked')){
            alert('checked' + v);
        } else {
            alert('un-checked' + v);
        }
    });

    var td  = document.createElement("td");

    td.appendChild(document.createTextNode('' + v));
    tr.appendChild(tdCheck);
    tr.appendChild(td);

    tbody.appendChild(tr);
}
table.appendChild(tbody);
document.appendChild(table)

这是jsfiddle:http://jsfiddle.net/n5GZW/2/

有人知道我做错了什么吗?

更新:更新了JSFiddle

"这里的'v'变量没有按复选框分配吗?"

嗯,它是指定的,但不是为每个复选框声明的。

在Javascript中,变量只有函数作用域。即使您尝试在循环的每次迭代中创建一个新变量,它也只是在函数级别声明的单个变量,由所有迭代共享。声明被提升到函数级别,只有赋值发生在循环内部。

您可以使用即时执行的函数表达式在循环中创建另一个范围,在那里您可以为每次迭代创建一个新变量:

for (var i=0;i<this.popupValues.length;i++) {
  (function(v){
    // code of the loop goes in here
    // v is a new variable for each iteration
  }(popupValues[i]));
}

您可以进行

   var table = document.createElement("table");
var tbody = document.createElement("tbody");

var popupValues = [
    "one", "two"
];
for (var i = 0; i < popupValues.length; i++) {
    var v = popupValues[i];
    var tr = document.createElement('tr');
    var tdCheck = document.createElement('td');
    var ChkBx = document.createElement('input');
    ChkBx.type = 'checkbox';
    ChkBx.value=v;
    tdCheck.appendChild(ChkBx);
    var td = document.createElement("td");
    td.appendChild(document.createTextNode('' + v));
    tr.appendChild(tdCheck);
    tr.appendChild(td);
    tbody.appendChild(tr);

    var self = this;
    $(ChkBx).click('change', function () {
        if ($(this).is(':checked')) {
            alert('check ' + $(this).val());
        } else {
            alert('un-checked');
        }
    });
}
table.appendChild(tbody);
document.body.appendChild(table)    

http://jsfiddle.net/n5GZW/4/
在单击时添加ChkBx.value=v;以获得类似$(this).val()的值

您本可以在SO中搜索event binding in for loop

这里有一个解决方案:

试试这个:

this.view = document.createElement("div");
var tbody = document.createElement("tbody");
var popupValues = {"A", "B"};
for (var i=0;i<this.popupValues.length;i++) {
    var v = popupValues[i];
    var tr  = document.createElement('tr');
    var tdCheck  = document.createElement('td');
    var ChkBx = document.createElement('input')
    ChkBx.type = 'checkbox';
    tdCheck.appendChild(ChkBx);
    var self = this;
    (function(val) {
      $(ChkBx).on('change', function(){
        if($(this).is(':checked')){
            alert('checked' + val);
        } else {
            alert('un-checked' + val);
        }
      });
    })(v);

    var td  = document.createElement("td");

    td.appendChild(document.createTextNode('' + v));
    tr.appendChild(tdCheck);
    tr.appendChild(td);

    tbody.appendChild(tr);
}
table.appendChild(tbody);
document.appendChild(table);