处理包含由事件监听器调用的"this"关键字的Object方法中的Scope

Cha*_*ins 4 javascript oop events scope

我把这种情况的缺乏理解归结为这个小问题.到目前为止,我认为这是我所知道的:

我有一个对象myDog(一个全局变量).Dog有一个成员变量el是一个html元素; 因为它是一个元素,我可以添加事件监听器.因此,当您单击时myDog.el,它会向控制台记录this.name和的值myDog.name.正如预期的那样,范围this.name是未定义的并且myDog.name是'tye'.当由click事件监听器调用时,this内部Dog.speak引用被单击的元素,即成员变量el,而不是对象Dog.由于它myDog是一个全局变量,因此无论函数的范围如何,它都可以进行备份,并且可以myDog.name很好地完成.

见下面的代码:

function Dog(name,id) {
    this.name = name ? name : "spot";
    this.id = id ? id : "dog";
    this.el = document.getElementById(this.id); // given there is a div with a matching    
    this.el.addEventListener("click",this.speak); // ignore IE for simplicity (attachEvent has its own 'this' scope issues)
}

Dog.prototype = {
    speak: function() {
        console.log("this.name: "+this.name+"\nmyDog.name: "+myDog.name);
    }
};

var myDog = new Dog("tye","dog1");
Run Code Online (Sandbox Code Playgroud)

所以...我的问题是

1)将对象附加到html元素的一些策略是什么,这样我可以this.el回到myDog(this.el所有者)而myDog不是全局变量?

2)在这种情况下全局变量是否是必要的邪恶?如果是这样,在这种情况下优雅使用它们的优秀策略是什么?例如,如果我想要100只狗实例化怎么办?我将如何处理所有这些全局变量Dog.speak

如果您想玩它,这是一个jsfiddle版本:http://jsfiddle.net/chadhutchins/Ewgw5/

小智 6

"1)将对象附加到html元素的策略是什么......"

既然你正在使用.addEventListener(),我建议利用它的一个功能,很少有人似乎知道...让你的Dog对象实现EventListener接口.

这在您的Dog数据及其相关元素之间建立了非常干净的关系.

只需要进行微小的更改.代码首先......解释如下.


演示: http : //jsfiddle.net/Ewgw5/1/

function Dog(name,id) {
    this.name = name ? name : "spot";
    this.id = id ? id : "dog";
    this.el = document.getElementById(this.id);

    // ---------------------------------v----no function!
    this.el.addEventListener("click", this);
}

Dog.prototype = {
    // Implement the `EventListener` interface   
    handleEvent: function(event) {
        switch (event.type) {
            case "click": return this.speak();
        }
    },
    speak: function() {
        console.log("this.name: "+this.name+"\nmyDog.name: "+myDog.name);
    }
};

var myDog = new Dog("tye","dog1");
Run Code Online (Sandbox Code Playgroud)

所以我所做的只是传递this构造函数addEventListener()而不是传递一个函数,然后我添加了一个handleEvent()方法Dog.prototype.

现在,当一个"click"事件发生时,它将调用该handleEvent()方法.该this方法的值将是您的Dog实例.所以,从那里你可以调用你需要的任何方法.

因为您将元素作为属性this,所以您可以通过它访问元素this.el.但这在技术上甚至不是必需的,因为元素也可以通过event对象获得event.currentTarget.


"2)在这种情况下全局变量是必要的邪恶......"

谢天谢地!


此行为应该是您的垫片的一部分.addEventListener().