我在javascript中有一个simpe对象,它有很少的方法。其中两个我想用window.setTimeout
函数定期调用。我目前的代码看起来像这样。
var shakeResolver = function () {
var resolveTimeout;
console.log(this);
var context = this;
this.startShakeResolve = function () {
this.resolveTimeout = window.setTimeout(this.call(context.stopShakeResolve, context), 2000);
$(window)
.on('devicemotion', this.onDeviceMotion);
};
this.onDeviceMotion = function (event) {};
this.stopShakeResolve = function (context) {
this.resolveTimeout = window.setTimeout(context.startShakeResolve, settings.interval);
};
}
问题显然是我误解了范围是如何工作的,看起来当从超时调用函数时,它是从另一个实际上不存在的上下文中调用的?
答案 0 :(得分:1)
call()
将调用函数的上下文作为第一个参数。这意味着您的this.call(context.stopShakeResolve, context)
使您的上下文成为context.stopShakeResolve
,这意味着当调用该函数时this
等同于context.stopShakeResolve
。
只是为了更清楚:
this.stopShakeResolve = function (context) {
this.resolveTimeout = window.setTimeout(context.startShakeResolve, settings.interval);
};
在其中没有一个名为shakeResolver
的函数,所以它会抛出一个异常,说它没有这种方式调用的属性或方法。将呼叫更改为以下内容:
this.stopShareResolve.call(this, context)
答案 1 :(得分:1)
修改后的代码:setTimeout的范围始终为window
对象。您可以使用call
apply
和bind
更改函数的上下文(较旧的IE浏览器不支持绑定IE< = 8)。
var shakeResolver = function() {
this.resolveTimeout;
console.log(this);
var context = this;
this.startShakeResolve = function() {
this.resolveTimeout = window.setTimeout(function() {
context.stopShakeResolve.apply(context, arguments);
}, 2000);
$(window).on('devicemotion', function(){
context.onDeviceMotion.apply(context, arguments);
});
};
this.onDeviceMotion = function(event) {
};
this.stopShakeResolve = function(context) {
this.resolveTimeout = window.setTimeout(function() {
context.startShakeResolve.apply(context, arguments)
}, settings.interval);
};
}