1

シンプルなシングルトンの実装を考えてみましょう:

var singleton = function (Constructor) {
    var singleton;
    return function () {
        if (!singleton) {
            singleton = new Constructor();
        }
        return singleton;
    };
};

シングルトン変数の宣言を引数に移動できます。

var singleton = function (Constructor, singleton) {
    return function () {
        if (!singleton) {
            singleton = new Constructor();
        }
        return singleton;
    };
};

だから私は単に副作用について興味があります。

もう 1 つの例:

var counter = (function (i) {
    return function () {
        i = (i || 0) + 1;
        return i;
    };
}());
4

2 に答える 2

4

シングルトン変数の宣言を引数に移動できます

まず、同じ数行のコード内で 2 つのまったくsingleton異なるものに同じ記号 ( ) を使用することで、結び目を作ることなくこれについて話すことができるようにしましょう。

名前を変更した2番目の例を次に示します。

var singleton = function (Constructor, instance) {
    return function () {
        if (!instance) {
            instance = new Constructor();
        }
        return instance;
    };
};

あなたがそれをした場合singleton、2つの引数で関数を呼び出すと が指定されinstance、渡すことConstructorが無意味になります —Constructorによって呼び出されることはありませんsingleton(繰り返しますが、2つの引数を渡した場合[そして2番目の引数が真実であった場合])。だから、それをするのは少し奇妙です。

しかし、あなたは副作用について尋ねました。関数内で仮引数に代入する場合、関連する外部効果はありません。たとえば、関数の外では何の効果もありません。

function foo(arg) {
    arg = 67;
}
var a = 42;
foo(a);
console.log(a); // Still 42

ただし、非厳密モードでは、ローカル変数ではなく引数に割り当てると、オーバーヘッドが発生するため、わずかなコストがかかります。これは魔法のarguments疑似配列に関連しています。非厳密モードでは、関数の仮引数とarguments疑似配列の間にリンクがあります。

function foo(a, b) {
    console.log(a);
    console.log(b);
    b = 42;
    console.log(arguments[1]);
}

これを次のように呼び出すと:

foo(1, 2);

私たちは見る

1
2
42

魔法に注意してください。仮引数に代入するとb、疑似配列が更新されましたarguments。(逆の方法でも機能します。) このリンクには、小さいながらも実質的なランタイム コストがかかります。

(厳格モードでは、まさにこの理由でリンクはありません。)

于 2013-08-07T09:08:35.667 に答える
1

行く限りclosure、2 つの実装に違いはありません。ただし、最初の例では、シングルトンは呼び出し元によって設定できません。

これらのサンプル関数の外でシングルトンを作成できたかどうかに基づいて、2 つの実装のどちらかを選択します。可能な場合は使用してください。model 2そうでない場合は使用してくださいmodel 1

于 2013-08-07T09:12:52.050 に答える