简体   繁体   English

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

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

I am trying to get an object inside the onclick event handler function. 我试图在onclick事件处理函数中获取一个对象。

But it is not working the way I expect it to. 但它并没有像我期望的那样发挥作用。

For example, if I run this code: 例如,如果我运行此代码:

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);
    };

}

What I expect is: 我的期望是:

this.id: 1
entry.id: 1

this.id: 2
entry.id: 2

this.id: 3
entry.id: 3

But what I get is: 但我得到的是:

this.id: 1
entry.id: 3

this.id: 2
entry.id: 3

this.id: 3
entry.id: 3

Why is the entry object always the entry with the id 3? 为什么条目对象始终是id为3的条目?

How can I get the correct entry object inside the click event handler? 如何在click事件处理程序中获取正确的条目对象?

One way to fix this is: 解决此问题的一种方法是:

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);

}

You can use a self-executing function (whose purpose is to provide a closure that entry.id will be bound to) to return you a new onclick handler that is bound to the particular id. 您可以使用自执行函数(其目的是提供entry.id将绑定的闭包)来返回绑定到特定id的新onclick处理程序。

If you don't do this, all your onclick handlers get bound to the same entry variable and end up with the last value it received during the for loop. 如果不这样做,所有onclick处理程序都绑定到相同的条目变量,并以for循环期间收到的最后一个值结束。

This is one of the tricky things about closure. 这是关闭的棘手问题之一。 You are creating those event handlers with a closure over entry . 您正在创建的事件处理程序具有关闭了entry They all have access to that variable, that exact variable. 他们都可以访问该变量,即确切的变量。 Consequently once those events fire they get only the last value set to entry. 因此,一旦这些事件触发,它们只会获得设置为最后一个值。 You need to break the closure. 你需要打破关闭。 Here is one way. 这是一种方式。

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);
  };
}

Note: I changed your for loop into a while just because it's the fastest way to loop in javascript when order isn't important and I think it's slick. 注意:我将for循环更改为一段时间只是因为当订单不重要时,这是在javascript中循环的最快方式,我认为它很光滑。

Added for completeness 添加完整性

There are some other methods designed to deal with this situation. 还有一些其他方法可以解决这种情况。 I find that I use them all the time. 我发现我一直都在使用它们。

In Ext there is createDelegate 在Ext中有createDelegate

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

For javascript 1.8.5 there is Function.prototype.bind 对于javascript 1.8.5,有Function.prototype.bind

myhandler.bind(scope, arguments)

Writing Function.prototype.bind is pretty easy ( lifted from here ) 编写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);
  };
};  

This is because of the way closures work in JavaScript. 这是因为闭包在JavaScript中的工作方式。 The onclick reference on all the 3 elements store the same function which after the loop has entry pointing to last entry. 所有3个元素的onclick引用存储相同的函数,该函数在循环后具有指向最后一个条目的条目。 Hence the result. 因此结果。 You can get your result by wrapping it in another function having the needed entry. 您可以通过将其包装到具有所需条目的另一个函数中来获得结果。 Following is one way to do it: 以下是一种方法:

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);
}

I've written a small post on this . 我已经写了一个小哨

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

相关问题 如何在事件处理程序中获取javascript事件对象? - How can I get the javascript event object inside a event handler? 如何在不手动单击屏幕来激发事件的情况下进入我的事件处理程序? - How can I get inside my event handler without manually clicking the screen to stimulate an event? 我如何访问标签内的javascript事件对象 - how do I get access to javascript event object inside tag 如何防止事件处理程序内的回调内的Default? - How can I preventDefault inside a callback inside an event handler? 如何在click事件处理程序中将对象添加到three.js场景? - How can I add an object to a three.js scene inside a click event handler? Javascript:如何引用拥有事件处理程序的对象? - Javascript: how do I refer to the object which owns the event handler? 如何从Marionette事件处理程序中选择元素? - How can I select an element from inside a Marionette event handler? 如何获取叠加层对象的事件处理程序? - How do I get the event handler of an overlay object? 如何将变量的当前值传递给事件处理程序(Javascript) - How can I pass the current value of a variable to an event handler (Javascript) 如何在JavaScript中以编程方式调用mouseover事件处理程序 - How can I call mouseover event handler programmatically in JavaScript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM