我有目标对象
function Foo() {
this.someVar = 'some var';
};
Foo.prototype.callback() {
console.log(this);
};
对象,将调用此回调
function Bar(callback) {
this.callback = callback;
};
Bar.prototype.onSomeAction = function() {
this.callback();
};
初始代码
foo = new Foo();
bar = new Bar();
bar.callback = foo.callback;
bar.onSomeAction();
结果:我已经登录到控制台Bar()的上下文而不是Foo()。 如何在Foo()回调中获取Foo()的上下文?
PS:我试过闭包
Foo.prototype.callback() {
var foo = this;
return function(foo) {
console.log(foo);
};
};
但它什么也没做。我还没有完全理解闭包:(
答案 0 :(得分:2)
原始代码不起作用的原因是方法调用中this
的值是它被调用的对象的值。这意味着当你说:
bar.callback = foo.callback;
然后你打电话:
bar.callback();
此处定义的代码:
Foo.prototype.callback = function () {
console.log(this);
};
被this
作为对bar
的引用而被调用,因为bar
位于方法调用的.
左侧。因此,无论何时将函数指定为对象属性,在该对象上调用它都将使用对象this
来调用它。
你也可以写:
function callback() {
console.log(this);
}
bar.callback = callback;
bar.callback();
您会发现this
仍然引用bar
。
实际上,如果您按上面所定义调用普通函数callback();
,您会发现this
是对全局对象的引用,通常是Web浏览器中的window
。那是因为所有全局变量和函数都是window
的属性,因此callback();
隐含window.callback();
this
的值取决于调用函数的对象在传递回调时可能是一个问题,因为有时您希望this
引用原始对象,该函数是属性的。设计绑定方法是为了解决这个问题,Yuri Sulyma给出了正确答案:
bar.callback = foo.callback.bind(foo);
但是,使用闭包执行此操作的方法是在匿名函数中捕获Foo实例,该函数在正确的对象上调用正确的方法:
foo = new Foo();
bar = new Bar();
bar.callback = function () {
foo.callback();
};
bar.onSomeAction();
这本质上是绑定的作用。实际上,我们使用闭包来调用我们自己的naive版本的bind:
Function.prototype.bind = function (obj) {
var fn = this;
return function () {
fn.call(obj);
};
};
call
让你调用一个明确定义this
值的函数。这允许您“设置上下文”调用函数,以便与调用obj.fn()
时调用bar.callback()
相同。由于我们致电foo.callback.bind(foo);
时,obj
为foo
且fn
为foo.callback
,因此调用bar.callback()
与调用{{}}相同{1}}。
Dalorzo的回答来自于此。他使用foo.callback()
显式设置上下文。
还有另一个函数用于设置名为call
的上下文,该函数还将表示函数参数的数组作为其第二个参数。这允许我们通过利用特殊的apply
变量来编写更完整的bind版本:
arguments
答案 1 :(得分:0)
尝试使用这些更改:
使用call
设置上下文:
bar.onSomeAction.call(foo);
我认为您的callback
功能需要更改为:
Foo.prototype.callback=function() {
console.log(this);
};
答案 2 :(得分:0)
bar.callback = foo.callback.bind(foo);
如有必要,您可以填充Function.prototype.bind()
:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility