繁体   English   中英

如何在javascript事件处理程序中获取对象?

[英]How can I get an object inside a javascript event handler?

我试图在onclick事件处理函数中获取一个对象。

但它并没有像我期望的那样发挥作用。

例如,如果我运行此代码:

var entries = [{id: 1},{id: 2},{id: 3}];

for (var i = 0; i < entries.length; i++) {

    var entry = entries[i];

    document.getElementById(entry.id).onclick = function () { 
        console.log("this.id: " + this.id);
        console.log("entry.id: " + entry.id);
    };

}

我的期望是:

this.id: 1
entry.id: 1

this.id: 2
entry.id: 2

this.id: 3
entry.id: 3

但我得到的是:

this.id: 1
entry.id: 3

this.id: 2
entry.id: 3

this.id: 3
entry.id: 3

为什么条目对象始终是id为3的条目?

如何在click事件处理程序中获取正确的条目对象?

解决此问题的一种方法是:

var entries = [{id: 1},{id: 2},{id: 3}];

for (var i = 0; i < entries.length; i++) {

    var entry = entries[i];

    document.getElementById(entry.id).onclick = (function (id) {
        return function () { 
            console.log("this.id: " + this.id);
            console.log("entry.id: " + id);
        };
    })(entry.id);

}

您可以使用自执行函数(其目的是提供entry.id将绑定的闭包)来返回绑定到特定id的新onclick处理程序。

如果不这样做,所有onclick处理程序都绑定到相同的条目变量,并以for循环期间收到的最后一个值结束。

这是关闭的棘手问题之一。 您正在创建的事件处理程序具有关闭了entry 他们都可以访问该变量,即确切的变量。 因此,一旦这些事件触发,它们只会获得设置为最后一个值。 你需要打破关闭。 这是一种方式。

function addClickHandlers() {
  var entries = [{id: 1},{id: 2},{id: 3}];
  var i = entries.length;
  while (i--) {
    var entry = entries[i];
    document.getElementById(entry.id).onclick = getClickHandler(entry);
  }
}  

function getClickHandler(entry) {
  return function() { 
    console.log("this.id: " + this.id);
    console.log("entry.id: " + entry.id);
  };
}

注意:我将for循环更改为一段时间只是因为当订单不重要时,这是在javascript中循环的最快方式,我认为它很光滑。

添加完整性

还有一些其他方法可以解决这种情况。 我发现我一直都在使用它们。

在Ext中有createDelegate

myhandler.createDelegate(scope, [arguments], [appendArgs]);

对于javascript 1.8.5,有Function.prototype.bind

myhandler.bind(scope, arguments)

编写Function.prototype.bind非常简单( 从这里解除

Function.prototype.bind = function(self, var_args) {
  var thisFunc = this;
  var leftArgs = Array.slice(arguments, 1);
  return function(var_args) {
    var args = leftArgs.concat(Array.slice(arguments, 0));
    return thisFunc.apply(self, args);
  };
};  

这是因为闭包在JavaScript中的工作方式。 所有3个元素的onclick引用存储相同的函数,该函数在循环后具有指向最后一个条目的条目。 因此结果。 您可以通过将其包装到具有所需条目的另一个函数中来获得结果。 以下是一种方法:

var entries = [{id: 1},{id: 2},{id: 3}];

for (var i = 0; i < entries.length; i++) {

    var entry = entries[i];

    function setOnClickHandler(entry) {
        document.getElementById(entry.id).onclick = function () { 
            console.log("this.id: " + this.id);
            console.log("entry.id: " + entry.id);
        };  
    }

    setOnClickHandler(entry);
}

我已经写了一个小哨

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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