1

我有一个无法解决的问题。

上下文是:我想要一个继承链,属于这个继承的对象的方法必须是事件处理程序,同时能够到达对象的属性。

我正在尝试编写没有“新”字的 JavaScript,而是使用带有一些继承层次结构的 Object.create()。所以首先采用这种方法。

所以我有一个其余对象的蓝图(myProto),然后我用 Object.create 创建对象(这样就没有闭包可以做分配thisthator的技巧self)。现在,当我使用该对象的方法来处理例如 div 上的单击事件时,this显然会引用 DOM 对象,并且我失去了访问对象属性的可能性。

var myProto = {
    init: function (name, value) {
        this.name = name;
        this.value = value;

        return this;
    },
    someHandler: function (e) {
        // Normally I would use this instead of e.target...

        e.target.innerHTML = this.name + this.value; // This does not refer to the object.
    }
};

var myObject = Object.create(myProto).init('myName', 'myValue');
document.getElementById('myDiv').onclick = myObject.someHandler;

这里的小提琴:http: //jsfiddle.net/pgPHM/

现在是“经典”方法:如果我使用新的 Constructor 表单,在闭包中分配它然后访问它会很容易,但是 Constructor.prototype 中的函数存在问题

var Constructor = function (name, value) {
    var self = this;

    self.name = name;
    self.value = value;
};

Constructor.prototype.someHandler = function () {/*self does not reach this here*/};

jsfiddle:http: //jsfiddle.net/ZcG3J/2/

如果没有这些棘手的上下文、闭包等,我真的不明白为什么 JS 对象没有真正的this或其他东西来引用自己……self

基本上问题是:

如何使用对象的方法作为事件处理程序,并且仍然能够访问该对象?

4

3 回答 3

2

除了使用时newthis在Javascript中是根据函数的调用方式来设置的。以正确的方式称呼它,this它将成为您想要的。我无法真正说出您要在问题中解决什么问题,但这this是确定的方式。

  1. 调用obj.method()-this将设置为objinside of method()
  2. 使用function.call()orfunction.apply()来控制你this自己。
  3. 进行正常的函数调用,例如func()并将this设置为全局对象或undefined取决于您是否处于严格模式。
  4. 使用.bind()(在现代浏览器中)创建一个函数存根,该函数存根将在.apply()内部自动用于将 this 的值“绑定”到函数的执行。
  5. 当您使用 调用构造函数时newthis将设置为构造函数内新创建的对象。
  6. 当您将回调函数作为参数传递给任何函数调用时(例如addEventListener(),调用函数有责任决定它希望将this指针设置为什么并且不会绑定到您自己的对象。 addEventListener()设置this为 DOM导致事件的对象。

对于您希望成为特定对象的方法调用的事件处理程序,您必须创建一种将方法调用与对象相关联的方法。您可以.bind()按照上面指定的方式使用,也可以使用可以引用this闭包中保存的值的匿名函数。

var self = this;
document.addEventListener('keyup', function(e) {
    self.handleKeys(e);
})

或者,使用.bind()

document.addEventListener('keyup', this.handleKeys.bind(this));

仅供参考,这两种方法之间没有任何真正的功能差异,因为.bind()只是创建一个闭包并执行第一个示例所做的事情,而是为您完成。

于 2013-10-27T21:24:17.737 回答
2

简单的。如果将函数作为方法调用而不是“裸”,则this总是指最后一个点之前的单词。所以而不是:

document.getElementById('myDiv').onclick = myObject.someHandler;

// You're just passing the function here, not calling it.
// It will be called by the onclick handler so `this` is changed

做这个:

document.getElementById('myDiv').onclick = function(){
    myObject.someHandler();

    // Here, you're actually calling it. So this is the word
    // before the last dot. Which is myObject
}

在更现代的 javascript 中,您当然可以使用bind

document.getElementById('myDiv').onclick = myObject.someHandler.bind(myObject);
于 2013-10-27T21:29:50.393 回答
1

The first problem in your jsfiddle is that self is a local variable for Constructor and it is not available outside of the function. What you think about the following code:

var Constructor = function(name, value) {
    var self = this;
    self.name = name;
    self.value = value;
    self.someHandler = function(e) {
        e.target.innerHTML = self.name + self.value; // self undefined    
    }
    return self;
};

var myObject = Constructor('myName', 'myValue');
document.getElementById('myDiv').onclick = myObject.someHandler;

JsFiddle -> http://jsfiddle.net/ZcG3J/4/

Is it structured as you want?

于 2013-10-27T21:32:49.780 回答