当直接从addEventListener调用时,为什么对象函数中的'this'是不同的

时间:2014-08-19 02:50:01

标签: javascript

为什么直接从addEventListener调用对象函数make this指向调用元素,但是从第三方函数调用使this指向对象而不是第三方函数?

var obj = {
    me: 'obj',
    objFunction: function(){
        document.body.innerHTML += this.me;
    }
};

document.addEventListener('mousedown', obj.objFunction);
document.addEventListener('mouseup', thirdParty);

function thirdParty(){
    obj.objFunction();
}

以上代码将在mousedown上打印undefined,在mouseup上打印'obj'http://jsfiddle.net/ana353Lk/1/

猜猜我好奇为什么它以这种方式工作有优势......

2 个答案:

答案 0 :(得分:2)

执行此操作时:

document.addEventListener('mousedown', obj.objFunction);

您只是传递对objFunction函数的引用。通过obj没有任何参考。因此,当事件系统调用回调objFunction时,只需将其称为普通函数,与此无异:

 var fn = obj.objFunction;
 fn();

因此,对象的上下文完全丢失,并且该方法被称为就像它是正常函数一样。有几种解决方法。

document.addEventListener('mousedown', function(e) {return obj.objFunction(e)});

document.addEventListener('mousedown', obj.objFunction.bind(obj));

这两种解决方法都创建了一个小的存根函数,它是事件处理程序调用的函数,然后存根转向并使用适当的对象引用调用obj.objFuntion(),这会导致this设置为obj


如果您不熟悉javascript中this的设置方式,那么值得一些阅读。这是one referenceanother reference。如何设置this取决于函数的调用方式(而不是函数的定义方式)。简而言之,有这些情况:

  1. 普通函数调用fn() - this设置为全局对象或undefined(在严格模式下)。

  2. 方法调用obj.method() - this在方法内设置为obj

  3. 使用fn.apply(x)fn.call(x) - this.apply().call()的第一个参数设置。

  4. 使用var newFn = fn.bind(x) - 调用newFn()时,this设置为传递给.bind()的第一个参数。

  5. newvar x = new Fn();中的构造函数一起使用 - 在构造函数函数this中将设置为Fn类型的新创建对象。

答案 1 :(得分:0)

var bind = function bind(context, name) {
    return function () {
        return context[name].apply(context, arguments);
    };
};

var obj = {
    me: 'obj',
    objFunction: function () {
        document.body.innerHTML += this.me;
    }
};

document.addEventListener('mousedown', bind(obj, "objFunction"));
document.addEventListener('mouseup', thirdParty);

function thirdParty() {
    obj.objFunction();
}