范围或闭包问题

时间:2014-09-19 22:44:49

标签: javascript service scope closures this

问题:

我有一个非常简单的代码片段。 我创建并使用成员变量" counter"和成员函数" start()"这会使计数器变量每秒增加1。 这里的问题是当start()作用于它时,计数器变量不会增加。 这让我头晕目眩。

假设:

我相信这是"这个"关键字或范围/结束问题,但我不确定究竟是什么错误。

代码:

var livePlayer = {
        counter : 0,
        liveIteration: null,

        start: function(){
            this.liveIteration = setInterval(this.incCounter, 1000);
        },

        incCounter: function(){
            this.counter++;
            alert(this.counter); <-- this should return 0, 1, 2, etc. but returns NAN instead
        }
    };

livePlayer.start();

的jsfiddle:

http://jsfiddle.net/justinwong12337/1wjdr0dh/

非常感谢您的帮助!

其他信息:

此对象及其成员是AngularJS服务的一部分,将由单独的控制器文件使用。

1 个答案:

答案 0 :(得分:3)

问题不在于范围或闭包。 :-)它与this一起,这是一个很滑的JavaScript概念。

在JavaScript中,函数调用期间this几乎完全由函数调用 how 设置,而不是函数定义的位置。它基本上是一种特殊形式的函数参数。 (这与其他具有相似语法的语言的含义完全不同。)您的案例中的特殊问题在于:

this.liveIteration = setInterval(this.incCounter, 1000);

当浏览器的计时器代码调用incCounter时,它会将this设置为全局对象,而不是您的对象。因此this.counter不是您对象上的counter属性(因为this没有引用您的对象),并且事情无法按预期工作。

你可以通过以下几种方式解决这个问题,最直接的可能就是ES5&#39; Function#bind(可以在旧浏览器上填充):

this.liveIteration = setInterval(this.incCounter.bind(this), 1000);

Function#bind返回一个函数,该函数在调用时调用原始函数,并将this设置为您给出的第一个参数。

更多探索(在我的博客上)