jquery click事件的Javascript变量范围问题

时间:2011-09-23 14:35:23

标签: javascript jquery arrays object scope

我正在尝试将存储在数组中的一系列对象分配给jquery click事件处理程序。

问题是,当事件触发时,我只引用数组中的最后一个对象。

我已经汇总了一个简单的例子来说明问题:

function dothis() {
    this.btns = new Array('#button1', '#button2');
}

// Add click handler to each button in array:
dothis.prototype.ClickEvents = function () {

    //get each item in array:
    for (var i in this.btns) {

        var btn = this.btns[i];
        console.debug('Adding click handler to button: ' + btn);

        $(btn).click(function () {
            alert('You clicked : ' + btn);
            return false;
        });
    }
}

var doit = new dothis();
doit.ClickEvents();

HTML表单包含几个按钮:

<input type="submit" name="button1" value="Button1" id="button1" />
<input type="submit" name="button2" value="Button2" id="button2" />

单击button1时,显示“您单击了#Button2”

似乎两个按钮单击处理程序都指向var btn中的同一个对象。

考虑到变量在for循环中,我无法理解为什么。

有什么想法吗?

5 个答案:

答案 0 :(得分:4)

您需要一个函数工厂来关闭循环变量,例如:

//get each item in array:
for (var i=0; i<this.btns.length; i++) {

    $(this.btns[i]).click(function(item) { 
        return function () {
            alert('You clicked : ' + item);
            return false;
        }
    }(this.btns[i]));

}

另一个好的选择是让jquery帮助你。使用jQuery.each()。这里的变量btn对于处理函数是本地的,因此不会在迭代之间重用。这允许您关闭它并保持其值。

$.each(this.btns, function() {
    var btn = this;
    $(this).click(function () {
        alert('You clicked : ' + btn);
        return false;
    }
});

答案 1 :(得分:2)

在一个事件处理程序中,'this'通常是指触发事件的元素,在这种情况下,它将是你的按钮

所以你的问题的解决方案相当容易,而不是引用btn变量,它生活在更高的范围内并且在事件处理程序触发之前很久就变异了,我们只是引用触发事件的元素并获取其ID < / p>

$(btn).click(function () {
  alert('You clicked : #' + this.id);
  return false;
});

注意:如果您的数组包含其他只有ID的选择器,这显然不会反映出这一点,只是继续显示ID

幸运的是,点击处理程序(以及所有其他事件处理程序afaik)为eventData采用了一个额外的参数,如下所示:

$(btn).click(btn, function (event) {
  alert('You clicked : #' + event.data);
  return false;
});

如果您传递了多个内容,请使用数组:

$(btn).click(['foo', 'bar'], function (event) {
  alert('this should be "foo": ' + event.data[0]);
  alert('this should be "bar": ' + event.data[1]);
  return false;
});

答案 2 :(得分:0)

你的问题在这里:

alert('You clicked : ' + btn);

btn保留上次在循环中调用的值。从事件中的按钮读取值。

    $(btn).data('selector', btn).click(function () {
        alert('You clicked : ' + $(this).data('selector'));
        return false;
    });

http://jsfiddle.net/Mc9Jr/1/

答案 3 :(得分:0)

你必须使用闭包。 我不确定我是否记得正确的语法,但你可以试试这个:

$(btn).click(function () {
    return function() {
        alert('You clicked : ' + btn);
        return false;
    }
});

答案 4 :(得分:0)

也许您只需要更改点击装订:

$(btn).click(function () {
    alert('You clicked : ' + $(this).attr('id'));
    return false;
});