为什么直接从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/
猜猜我好奇为什么它以这种方式工作有优势......
答案 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 reference和another reference。如何设置this
取决于函数的调用方式(而不是函数的定义方式)。简而言之,有这些情况:
普通函数调用fn()
- this
设置为全局对象或undefined
(在严格模式下)。
方法调用obj.method()
- this
在方法内设置为obj
。
使用fn.apply(x)
或fn.call(x)
- this
由.apply()
或.call()
的第一个参数设置。
使用var newFn = fn.bind(x)
- 调用newFn()
时,this
设置为传递给.bind()
的第一个参数。
将new
与var 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();
}