Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何有效地向特定JavaScript对象实例注册DOM事件_Javascript_Javascript Events - Fatal编程技术网

如何有效地向特定JavaScript对象实例注册DOM事件

如何有效地向特定JavaScript对象实例注册DOM事件,javascript,javascript-events,Javascript,Javascript Events,在我的web应用程序中,我有一个自定义对象,我用对象函数构造函数定义了它,并通过构造函数原型应用了各种共享属性 MyObject = function (Name) { this.Name = Name; this.ListItem1 = document.createElement('li'); this.ListItem1.onclick = this.SetActive; this.ListItem2 = document.createElement('li'); th

在我的web应用程序中,我有一个自定义对象,我用对象函数构造函数定义了它,并通过构造函数原型应用了各种共享属性

MyObject = function (Name) {
  this.Name = Name;
  this.ListItem1 = document.createElement('li');
  this.ListItem1.onclick = this.SetActive;
  this.ListItem2 = document.createElement('li');
  this.ListItem2.onclick = this.SetActive;
}

MyObject.prototype.SetActive = function () {
  alert('SetActive: ' + this.Name);
}
现在这是一个简化的示例,我的实际对象有更多的DOM元素附加到它,每个DOM元素都有许多不同的事件侦听器。我的对象还有许多其他属性和方法。我还可能有数千个这个对象的实例,所以代码效率很重要

我现在的问题是,当触发DOM事件时,事件处理程序的“this”属性被设置为实际的DOM元素,而不是我的对象实例

例如:

var HelloObj = new MyObject('Hello');
HelloObj.SetActive();    
    //This alerts 'SetActive: Hello'

HelloObj.ListItem1.click();    
    //This alerts 'SetActive: undefined' because 'this' in SetActive
    //becomes ListItem1 and obviously ListItem1.Name is undefined
那么,如何将DOM元素的事件处理程序设置为函数指针(不是每个事件处理程序的新函数实例,当存在大量对象实例时,这将是低效的),但仍然保留与“this”相关的对象实例本身的上下文呢?

请像这样尝试
bind()

this.ListItem1.onclick = this.SetActive.bind(this); 
//and so on

我提出并正在使用的解决方案是将对象实例的引用附加到DOM元素,然后使用事件处理程序的包装函数通过该引用调用所需的函数:

MyObject = function (Name) {
  this.Name = Name;

  this.ListItem1 = document.createElement('li');
  this.ListItem1.Context = this;
  this.ListItem1.onclick = this.SetActiveHandler;

  this.ListItem2 = document.createElement('li');
  this.ListItem2.Context = this;
  this.ListItem2.onclick = this.SetActiveHandler;
}

MyObject.prototype.SetActiveHandler = function () {
  this.Context.SetActive();
}
MyObject.prototype.SetActive = function () {
  alert('SetActive: ' + this.Name);
}
这解决了我所有的问题,尽管我并不完全满意,因为有一些陷阱。从视觉上看,它并不漂亮,而且更复杂。在编程上,它创建了一个循环引用,我知道这通常是不赞成的,尽管在我的情况下,我认为它不应该引起任何问题,因为我只担心现代浏览器,我相信循环引用是完全包含的,因此如果所有DOM元素都从文档中删除了,并且我删除了对MyObject实例本身的引用,那么所有内容都应该被完全垃圾收集(对此的一些反馈将不胜感激)。我知道将自定义属性附加到DOM元素也被认为是一种不好的做法,尽管我不知道这对于现代浏览器来说是否仍然是一个问题(同样,一些反馈会很好)。它还稍微中断了面向对象的流程,如果要通过第二个函数,我希望将事件处理程序直接附加到
SetActive()


有没有人有其他的解决办法,或者说有没有人能说明我是否真的制造了比我解决的更多的问题

我忘记了bind(),打得好。这样做的唯一问题是
bind()
创建了一个新函数,因此如果我像这样分配每个事件处理程序,我将为每个事件处理程序创建一个新函数,这正是我试图避免的。我想可能有办法在对象原型中使用bind来实现我想要的东西…@user1084447我肯定有办法,但是我认为你必须重新组织代码来实现这样的目标。目前我对一些重组持开放态度。在这种情况下,最大限度地提高效率将是实现本项目所需性能的一部分。有什么想法吗?很难想出有用的想法。使用
prototype
已经是一种很好的方法。