javascript中的范围

时间:2012-10-04 08:06:02

标签: javascript scopes

我在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);

 };

}

问题显然是我误解了范围是如何工作的,看起来当从超时调用函数时,它是从另一个实际上不存在的上下文中调用的?

2 个答案:

答案 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 applybind更改函数的上下文(较旧的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);

    };
}