为什么在回调中没有绑定“this”时,我会使用setTimeout丢失上下文
在下面的代码中,您可以看到在3个位置调用onTime
一次从课堂上来。哪个工作正常。
一次来自课外。哪个工作正常。
一旦定时器触发呼叫。 “这个”需要绑定方法
有没有办法在每次回调时不使用bind来强制上下文?
var MyBaseClass = function () {
"use strict";
this._base = {};
this._base.baseFunc = function () {
console.log('baseFunc called')
};
return this._base;
};
var TestClass = function () {
"use strict";
if (TestClass.prototype._singletonInstance) {
return TestClass.prototype._singletonInstance;
}
TestClass.prototype._singletonInstance = this;
this._timer = {};
console.log('constructor')
};
TestClass.prototype = new MyBaseClass(); // Set prototype to MyBaseClass
TestClass.prototype.constructor = TestClass; // Set constructor back to TestClass
TestClass.prototype.onTime = function () {
"use strict";
console.log('ontime called')
console.log(this, "<--- why do i lose context")
this.baseFunc()
}
TestClass.prototype.init = function () {
"use strict";
console.log('local')
this.onTime()
//this._timer = setTimeout(this.onTime.bind(this),500)// works
this._timer = setTimeout(this.onTime, 500) // no work
};
var asdf = new TestClass()
asdf.init()
console.log('global')
asdf.onTime()
答案 0 :(得分:1)
请注意,您只将一个函数传递给setTimeout,而不是一个对象,因此setTimeout可能无法知道您想要的上下文。解决方案是使用包装函数来保存上下文(dojo的故障,在许多其他lib中称为bind)。这个是强制上下文的方式,我不确定你为什么要寻找其他东西。一个选项可能是在构造函数中绑定一次,然后您可以传递函数而不必担心上下文,如下所示:
this.onTime = this.onTime.bind(this);
// now you can pass the function around
this._timer = setTimeout(this.onTime, 500) // works
澄清并尝试处理有关原型的问题......
你在构造函数中绑定函数的原因(我假设你的init函数将被用作),而不是其他任何地方,是因为你构造(使用new
)第二个对象,您希望该对象成为在其上执行的函数的上下文。直接执行函数(myObj.myFunc
)时,您可以免费获得此行为,但在传递函数(setTimeout(myObj.myFunc, 50)
或var callback = myObj.myFunc;
)时需要小心。这是您遇到的核心问题,您可以使用两种策略:
这基本上就是你自己开发的方法,当你将函数传递给setTimeout
时,你将它绑定到你的对象上。我仍然不确定我理解为什么你不喜欢这种技术,但它是一个有效的模式,许多lib等使用。
setTimeout(myObj.myFunc.bind(myObj), 50);
这是你可以绑定的最快的时间 - 你在原型上设置函数时无法绑定,因为尚未构造对象,你会绑定什么?使用这种技术,您可以正常调用setTimeout,并且知道您传递的函数已经“预先绑定”。
var myObjClass = function(){
this.myFunc = this.myFunc.bind(this);
}
myObjClass.prototype.myFunc = function(){};
var myObj = new myObjClass();
setTimeout(myObj.myFunc);
答案 1 :(得分:0)
保持上下文在setTimeout中创建一个新方法。您正在传递没有上下文关联的方法引用。
TestClass.prototype.init = function () {
"use strict";
console.log('local')
this.onTime();
var me = this;
//this._timer = setTimeout(this.onTime.bind(this),500)// works
this._timer = setTimeout(function(){
me.onTime();
}, 500)
};