1

私は JavaScript に比較的慣れていないため、このエラーが発生する理由を理解するのに苦労しています。

TypeError: readonly プロパティに割り当てようとしました。MyTimer.js: 35

strict モードを使用しているため、このエラーが表示されることは理解していますが、このオブジェクトのデバッグに役立つようにstrict モードを有効にしました。

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);
    };

}

だから私はまだ完全には理解していません - なぜこの変更はそれを修正したのですか? 結局スコープの問題でしたか?

4

3 に答える 3

1

次の厳密なモード制限が説明だと思います。

this が厳密モード コード内で評価される場合、この値はオブジェクトに強制されません。null または未定義の this 値はグローバル オブジェクトに変換されず、プリミティブ値はラッパー オブジェクトに変換されません。関数呼び出し (Function.prototype.apply および Function.prototype.call を使用して行われた呼び出しを含む) を介して渡された this 値は、渡された this 値をオブジェクトに強制しません (10.4.3、11.1.1、15.3.4.3、15.3. 4.4)。

電話すると

return Singleton();

値は実際にはthis未定義になります。これをやってみてください。

return {
    getInstance: function () {
        return instance || new Singleton();
    }
};
于 2013-03-29T20:14:25.383 に答える
1

私があなたのコードを正しく読んでいるなら、ここにスコープの問題があります

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

そのはず

this.timer = setInterval(function()
{
    instance.tasks.fire(); 
}, 1000);
于 2013-03-29T19:52:50.717 に答える
0

これが原因かどうかはわかりませんが、「tasks = $.Callbacks();」という行のようです。「this.tasks = $.Callbacks();」にする必要があります。また、インスタンスをコールバックとして提供しているため、「this」バインディングが失われます。あなたは「これ」で何かを呼び出す体を機能させます。代わりに、外側のクロージャでこれをキャプチャする var を使用する必要があります (「instance」のように見えます)。

たとえば、問題のメソッドは次のようになります。

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

于 2013-03-29T19:52:57.420 に答える