JavaScript回调范围 [英] JavaScript Callback Scope
问题描述
我在引用我的对象回调函数遇到一些麻烦普通的旧的JavaScript(无框架)。
I'm having some trouble with plain old JavaScript (no frameworks) in referencing my object in a callback function.
function foo(id) {
this.dom = document.getElementById(id);
this.bar = 5;
var self = this;
this.dom.addEventListener("click", self.onclick, false);
}
foo.prototype = {
onclick : function() {
this.bar = 7;
}
};
现在,当我创建一个新的对象(DOM加载之后,具有跨度#测试)
Now when I create a new object (after the DOM has loaded, with a span#test)
var x = new foo('test');
在'本'的onclick函数指向跨度#测试里面,而不是Foo对象。
The 'this' inside the onclick function points to the span#test and not the foo object.
我如何获得的onclick函数内到我的Foo对象的引用?
How do I get a reference to my foo object inside the onclick function?
推荐答案
的(摘录了一些解释,这是隐藏在对方的回答评论)的
问题在于以下行:
this.dom.addEventListener("click", self.onclick, false);
在这里,你传递给被用作回调函数对象。当事件触发时,函数被调用,但现在它与任何对象没有关联(本)。
Here, you pass a function object to be used as callback. When the event trigger, the function is called but now it has no association with any object (this).
的问题可以通过在一个封闭包裹功能(与它的对象参考)如下来解决:
The problem can be solved by wrapping the function (with it's object reference) in a closure as follows:
this.dom.addEventListener(
"click",
function(event) {self.onclick(event)},
false);
由于自变量分配的这个的创建关闭时,关闭功能会记得自变量的值时,它被称为在稍后的时间。
Since the variable self was assigned this when the closure was created, the closure function will remember the value of the self variable when it's called at a later time.
要解决这个问题的另一种方法是使一个效用函数(和避免使用变量绑定的这个的):
An alternative way to solve this is to make an utility function (and avoid using variables for binding this):
function bind(scope, fn) {
return function () {
fn.apply(scope, arguments);
};
}
然后更新code看起来像:
The updated code would then look like:
this.dom.addEventListener("click", bind(this, this.onclick), false);
<一个href=\"https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind\"><$c$c>Function.prototype.bind$c$c>是的ECMAScript 5的一部分,并提供相同的功能。所以,你可以这样做:
Function.prototype.bind
is part of ECMAScript 5 and provides the same functionality. So you can do:
this.dom.addEventListener("click", this.onclick.bind(this), false);
有关不支持ES5还没有浏览器, MDN提供以下垫片:
For browsers which do not support ES5 yet, MDN provides the following shim:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP
? this
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
这篇关于JavaScript回调范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!