JavaScript单例类型错误:为什么严格模式会标记这个?

时间:2013-03-29 19:43:07

标签: javascript jquery typeerror

我对JavaScript比较陌生,我很难理解为什么会出现这种错误:

  

TypeError:尝试分配给readonly属性。 MyTimer.js:35

我知道显示此错误是因为我使用严格模式,但我启用了严格模式来帮助我调试此对象。

创建MyTimer单例的调用是:

var simTimer = new SimTimer();

然后我在MyTimer中添加要执行的任务,如下所示:

var task = function(){
    console.log("performing task.");
};

simTimer.addTask(task);

最后,这是MyTimer对象(第35行标记):

var MyTimer = (function () {
    "use strict";

    // var timer;
    var tasks;

    /**
     * If an instance of MyTimer exists, it will be saved to this variable and returned
     * by any subsequent calls to this constructor, thus only one instance (stored in this
     * variable) will be accessible.
     * @private
     */
    var instance;

    /**
     * Called to initialize this MyTimer Object, or return #instance if it already contains
     * an instance of this Object.
     */
    function Singleton() {
        if (instance) {
            return instance;
        }
        instance = this;
        tasks = $.Callbacks();
        this.timer = setInterval(function()
        {
            this.tasks.fire();
        }, 1000);//<---- THIS IS LINE 35!

        this.addTask = function(task)
        {
            this.tasks.add(task);
        };

        this.removeTask = function(task)
        {
            this.tasks.remove(task);
        };
    }

    //instance accessor
    Singleton.getInstance = function () {
        return instance || new Singleton();
    };

    return Singleton();

}());

我没有掌握什么?我已经阅读了很多关于Module Patterns的文档,并且之前已成功写过单身人士 - 所以我在哪里出错?

**编辑:**

通过删除var tasks并使用Singletonthis内创建,我能够获得正确的行为。该函数的工作版本现在如下所示:

function Singleton() {
    if (instance) {
        return instance;
    }
    instance = this;

    this.tasks = $.Callbacks();

    this.timer = setInterval(function(){
        instance.tasks.fire();
    }, 1000);
    this.removeTask = function(task)
    {
        instance.tasks.remove(task);
    };
    this.addTask = function(task)
    {
        instance.tasks.add(task);
    };

}

所以我仍然不完全明白 - 为什么这个改变会解决它?这毕竟是一个范围问题吗?

3 个答案:

答案 0 :(得分:1)

如果我正确地阅读您的代码,那么您有一个范围问题

this.timer = setInterval(function()
{
    this.tasks.fire();  <-- this will be in window scope
}, 1000);

应该是

this.timer = setInterval(function()
{
    instance.tasks.fire(); 
}, 1000);

答案 1 :(得分:1)

我认为以下严格模式限制是解释。

  

如果在严格模式代码中评估,则此值为   没有强迫对象。此值为null或undefined不是   转换为全局对象并且不转换原始值   包装对象。该值通过函数调用传递   (包括使用Function.prototype.apply和。进行的调用   Function.prototype.call)不强制将此值传递给   对象(10.4.3,11.1.1,15.3.4.3,15.3.4.4)。

致电时

return Singleton();

this值实际上是未定义的。试着这样做。

return {
    getInstance: function () {
        return instance || new Singleton();
    }
};

答案 2 :(得分:0)

不确定这是否是原因,但看起来像是&#34; tasks = $ .Callbacks();&#34;应该是&#34; this.tasks = $ .Callbacks();&#34;。此外,当您提供一个实例作为回调时,您将失去这个&#39;这个&#39;捆绑。你可以使用&#34;这个来调用任何东西。&#34;应该使用一个var来在外部闭包中捕获它(看起来像&#39;实例&#39;那样。

因此,例如,所讨论的方法将为:

this.timer = setInterval(function()         {             instance.tasks.fire();         },1000);