JavaScriptにシングルトンを実装する最も簡単で最もクリーンな方法は?


300

JavaScriptでシングルトンパターンを実装する最も簡単でクリーンな方法は何ですか?


15
受け入れられた回答がシングルトンではないことへの反対票。これは単なるグローバル変数です。
mlibby 2013

5
これは大量の情報ですが、実際にはさまざまなJSデザインパターンの違いを説明しています。それは私を大いに助けました:addyosmani.com/resources/essentialjsdesignpatterns/book
Justin

回答:


315

最も簡単な方法は、単純なオブジェクトリテラルを宣言することだと思います。

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};

シングルトンインスタンスにプライベートメンバーが必要な場合は、次のようにすることができます。

var myInstance = (function() {
  var privateVar = '';

  function privateMethod () {
    // ...
  }

  return { // public interface
    publicMethod1: function () {
      // all private members are accessible here
    },
    publicMethod2: function () {
    }
  };
})();

これはモジュールパターンと呼ばれ基本的に、クロージャーの使用を利用して、オブジェクトのプライベートメンバーをカプセル化できます。

更新:シングルトンオブジェクトの変更を防止したい場合は、ES5 メソッドを使用してフリーズできますObject.freeze

これにより、オブジェクトが不変になり、オブジェクトの構造と値が変更されなくなります。

さらに、ES6を使用している場合は、ESモジュールを使用してシングルトンを非常に簡単に表すことができ、モジュールスコープで変数を宣言することでプライベート状態を保持することもできます

// my-singleton.js
const somePrivateState = []

function privateFn () {
  // ...
}

export default {
  method1() {
    // ...
  },
  method2() {
    // ...
  }
}

その後、シングルトンオブジェクトをインポートして使用できます。

import myInstance from './my-singleton.js'
// ...

46
+1グローバル変数を持つ言語で「シングルトンパターン」を探すのは少し奇妙ではありませんか???
ビクター

4
モジュールパターンを使用して、パブリックメンバーは他のパブリックメンバーにどのようにアクセスしますか?つまり、どのようにpublicMethod1呼び出すpublicMethod2でしょうか?
typeof

4
@トム、ええ、パターンはクラスベースのOOP言語で生まれました- getInstance私は静的メソッドとプライベートコンストラクターを含む多くの実装を覚えていますが、IMO、これはシングルトンオブジェクトを構築する最も「簡単な」方法ですJavaScriptでは、最終的には同じ目的を満たします-単一オブジェクトであり、再度初期化することはできません(コンストラクタはなく、単なるオブジェクトです)。リンクしたコードについて、いくつかの問題がaありbますa === window。変数と変数の宣言を入れ替えてテストしてください。乾杯。
CMS

15
@Victor –そのような言語で「シングルトンパターン」を探すのは奇妙なことではありません。多くのオブジェクト指向言語はグローバル変数を利用していますが、それでもシングルトンが使用されています。シングルトンは、特定のクラスのオブジェクトが1つしかないことを保証するだけではありません。シングルトンには他にもいくつかの機能があります:1)最初の使用時に初期化する必要があります(これは初期化の遅延を意味するだけでなく、オブジェクトが実際に使用できる状態であることも保証します)2)スレッドセーフである必要があります。モジュールパターンは、シングルトンパターンの代わりに使用できますが、ブラウザでのみ使用できます(常に使用できるわけではありません)。
skalee

55
これは受け入れられる答えではありません。これはシングルトンではありません!これは単なるグローバル変数です。両者には違いのある世界があります。
mlibby 2013

172

私は最もクリーンなアプローチは次のようなものだと思います:

var SingletonFactory = (function(){
    function SingletonClass() {
        //do stuff
    }
    var instance;
    return {
        getInstance: function(){
            if (instance == null) {
                instance = new SingletonClass();
                // Hide the constructor so the returned object can't be new'd...
                instance.constructor = null;
            }
            return instance;
        }
   };
})();

その後、次のように関数を呼び出すことができます

var test = SingletonFactory.getInstance();

4
備考:オリジナルのコンストラクタが使用して再度読み込むことができますdelete instance.constructorx = SingletonClass.getInstance();delete x.constructor;new x.constructor;
ロブW

var test = SingletonClass.getInstance()-とてもきれいに見えたり、JSのようには見えません a = new Foo();で終わるその他の魂 b = new Foo(); a === b // true
Matthias

3
「getInstance」部分全体で、工場のような匂いがします。
Lajos Meszaros

1
Object.createでインスタンスを複数作成できるため、これはシングルトンではありません。
AndroidDev 2017年

フィドルが壊れている
HoffZ 2018

103

シングルトンパターンの代わりとして使用されるモジュールパターンに同意するかどうかはわかりません。完全に不要な場所でシングルトンが使用および乱用されることはよくあります。モジュールパターンがシングルトンを使用しない場合、モジュールパターンはシングルトンではありませんが、モジュールパターンが多くのギャップを埋めると確信しています。

モジュールパターン:

var foo = (function () {
    "use strict";
    function aPrivateFunction() {}
    return { aPublicFunction: function () {...}, ... };
}());

Fooが宣言されると、モジュールパターンで初期化されたすべてが発生します。さらに、モジュールパターンを使用してコンストラクターを初期化できます。コンストラクターは複数回インスタンス化できます。モジュールパターンは多くのジョブに適したツールですが、シングルトンと同等ではありません。

シングルトンパターン:

ショートフォーム
var Foo = function () {
    "use strict";
    if (Foo._instance) {
        //this allows the constructor to be called multiple times
        //and refer to the same instance. Another option is to
        //throw an error.
        return Foo._instance;
    }
    Foo._instance = this;
    //Foo initialization code
};
Foo.getInstance = function () {
    "use strict";
    return Foo._instance || new Foo();
}
長い形式、モジュールパターンを使用
var Foo = (function () {
    "use strict";
    var instance; //prevent modification of "instance" variable
    function Singleton() {
        if (instance) {
            return instance;
        }
        instance = this;
        //Singleton initialization code
    }
    //instance accessor
    Singleton.getInstance = function () {
        return instance || new Singleton();
    }
    return Singleton;
}());

私が提供したシングルトンパターンの両方のバージョンで、コンストラクター自体をアクセサーとして使用できます。

var a,
    b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true

この方法でコンストラクタを使いたくない場合は、if (instance)ステートメントでエラーをスローし、長い形式をそのまま使用できます。

var a,
    b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true

また、シングルトンパターンは、暗黙のコンストラクター関数パターンにうまく適合することにも言及する必要があります。

function Foo() {
    if (Foo._instance) {
        return Foo._instance;
    }
    //if the function wasn't called as a constructor,
    //call it as a constructor and return the result
    if (!(this instanceof Foo)) {
        return new Foo();
    }
    Foo._instance = this;
}
var f = new Foo(); //calls Foo as a constructor
-or-
var f = Foo(); //also calls Foo as a constructor

4
シングルトンが悪いアイデアや良いアイデアであることについて、私は何も言いませんでした。シングルトンの実装は、Javaの制限とパターンをまったく理解していないかのように混同しているため、必要以上に複雑であると述べました。これは、JavaScriptで匿名関数を簡単に使用できる場合に、コンストラクター関数とメソッドを作成して戦略パターンを実装するようなものです。
エサイリヤ2013年

11
@Esailija、シングルトンパターンが理解できないように聞こえます。シングルトンパターンは、クラスのインスタンス化を1つのオブジェクトに制限する設計パターンです。var singleton = {}その定義に適合しません。
zzzzBov 2013年

9
制限があるため、Javaなどの言語にのみ適用されます。var singleton = {}JavaScriptでシングルトンを実装する方法です
エサイリヤ2013年

2
@Esailija、「クラストではなくオブジェクトが使用されるプロトタイプベースのプログラミング言語では...」JavaScriptにはクラスの概念があるため、適用されません。
zzzzBov 2013年


18

es6

class Singleton {
  constructor () {
    if (!Singleton.instance) {
      Singleton.instance = this
    }
    // Initialize object
    return Singleton.instance
  }
  // Properties & Methods
}

const instance = new Singleton()
Object.freeze(instance)

export default instance

1
シングルトンが他のクラスのラッパーであり、instanceフィールドのみを持つ場合、フリーズは理にかなっています。現在の(にinstance設定されているthis)ため、このクラスには他のフィールドも含まれる可能性があり、凍結は意味がありません。
thisismydesign

10

以下はノードv6で動作します

class Foo {
  constructor(msg) {

    if (Foo.singleton) {
      return Foo.singleton;
    }

    this.msg = msg;
    Foo.singleton = this;
    return Foo.singleton;
  }
}

私たちはテストします:

const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }

8

ES6では、これを行う正しい方法は次のとおりです。

class MyClass {
  constructor() {
    if (MyClass._instance) {
      throw new Error("Singleton classes can't be instantiated more than once.")
    }
    MyClass._instance = this;

    // ... your rest of the constructor code goes after this
  }
}

var instanceOne = new MyClass() // Executes succesfully 
var instanceTwo = new MyClass() // Throws error

または、2番目のインスタンスの作成時にエラーがスローされないようにするには、次のように最後のインスタンスを返すだけです。

class MyClass {
  constructor() {
    if (MyClass._instance) {
      return MyClass._instance
    }
    MyClass._instance = this;

    // ... your rest of the constructor code goes after this
  }
}

var instanceOne = new MyClass()
var instanceTwo = new MyClass()

console.log(instanceOne === instanceTwo) // logs "true"


こんにちは、インスタンスを使用していてコードが機能していなかったため、_instanceとinstanceの違いを知るのを手伝ってくれますか
Abhinav bhardwaj

とには技術的な違いはinstanceありません_instance。アンダースコアを前に付けたプライベート変数に名前を付けるのは、プログラミング言語の命名規則にすぎません。あなたのコードが機能しない理由は、あなたがthis.instance代わりに使用しているためだと思いますMyClass.instance
UtkarshPramodGupta

7

猫の皮をむく方法は複数あります:)好みや特定のニーズに応じて、提案されたソリューションのいずれかを適用できます。個人的には、可能な場合はいつでも(プライバシーが必要ない場合)CMSの最初のソリューションを採用します。質問は最もシンプルでクリーンなものだったので、それが勝者です。あるいは:

var myInstance = {}; // done!

これ(私のブログからの引用)...

var SingletonClass = new function() { 
    this.myFunction() { 
        //do stuff 
    } 
    this.instance = 1; 
}

プライベート変数を必要としないため、あまり意味がありません(私のブログの例もそうではありません)。したがって、次のコードとほとんど同じです。

var SingletonClass = { 
    myFunction: function () { 
        //do stuff 
    },
    instance: 1 
}

コードスニペット2に構文エラーが含まれています。書くことはできませんthis.f(){}
xoxox

7

私は自分の回答を非推奨にしています。他の回答をご覧ください。

通常、シングルトンパターンではないモジュールパターン(CMSの回答を参照)で十分です。ただし、シングルトンの機能の1つは、オブジェクトが必要になるまで初期化が遅延することです。モジュールパターンにはこの機能がありません。

私の命題(CoffeeScript):

window.singleton = (initializer) ->
  instance = undefined
  () ->
    return instance unless instance is undefined
    instance = initializer()

これはJavaScriptでこれにコンパイルされました:

window.singleton = function(initializer) {
    var instance;
    instance = void 0;
    return function() {
        if (instance !== void 0) {
            return instance;
        }
        return instance = initializer();
    };
};

その後、私は以下を行うことができます:

window.iAmSingleton = singleton(function() {
    /* This function should create and initialize singleton. */
    alert("creating");
    return {property1: 'value1', property2: 'value2'};
});


alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up

必要がないのに、なぜモジュールをロードするのですか?モジュールをロードする必要がある場合は、モジュールをロードして初期化します。
エサイリヤ2013年

6

短い答え:

JavaScriptの非ブロッキング性のため、JavaScriptのシングルトンは実際には醜いです。グローバル変数は、これらすべてのコールバックなしで、アプリケーション全体を通じて1つのインスタンスを提供します。モジュールパターンは、内部を内部的にインターフェイスの背後に静かに隠します。@CMSの回答を参照してください。

しかし、シングルトンが必要だったので…

var singleton = function(initializer) {

  var state = 'initial';
  var instance;
  var queue = [];

  var instanceReady = function(createdInstance) {
    state = 'ready';
    instance = createdInstance;
    while (callback = queue.shift()) {
      callback(instance);
    }
  };

  return function(callback) {
    if (state === 'initial') {
      state = 'waiting';
      queue.push(callback);
      initializer(instanceReady);
    } else if (state === 'waiting') {
      queue.push(callback);
    } else {
      callback(instance);
    }
  };

};

使用法:

var singletonInitializer = function(instanceReady) {
  var preparedObject = {property: 'value'};
  // calling instanceReady notifies singleton that instance is ready to use
  instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);

// get instance and use it
s(function(instance) {
  instance.doSomething();
});

説明:

シングルトンは、アプリケーション全体で1つ以上のインスタンスを提供します。それらの初期化は、最初の使用まで遅延されます。初期化にコストがかかるオブジェクトを扱う場合、これは非常に重要です。高価なは通常I / Oを意味し、JavaScriptではI / Oは常にコールバックを意味します。

のようなインターフェースを提供する回答は信用しないでくださいinstance = singleton.getInstance()

インスタンスの準備ができているときにコールバックを実行しないと、イニシャライザがI / Oを実行しても機能しません。

ええ、コールバックは常にオブジェクトのインスタンスをすぐに返す関数呼び出しよりも醜く見えます。しかし、繰り返しになりますが、I / Oを行う場合、コールバックは必須です。I / Oを行いたくない場合、インスタンス化はプログラムの開始時にそれを行うのに十分安価です。

例1、安価な初期化子:

var simpleInitializer = function(instanceReady) {
  console.log("Initializer started");
  instanceReady({property: "initial value"});
}

var simple = singleton(simpleInitializer);

console.log("Tests started. Singleton instance should not be initalized yet.");

simple(function(inst) {
  console.log("Access 1");
  console.log("Current property value: " + inst.property);
  console.log("Let's reassign this property");
  inst.property = "new value";
});
simple(function(inst) {
  console.log("Access 2");
  console.log("Current property value: " + inst.property);
});

例2、I / Oによる初期化:

この例ではsetTimeout、高価なI / O操作を偽装しています。これは、JavaScriptのシングルトンが本当にコールバックを必要とする理由を示しています。

var heavyInitializer = function(instanceReady) {
  console.log("Initializer started");
  var onTimeout = function() {
    console.log("Initializer did his heavy work");
    instanceReady({property: "initial value"});
  };
  setTimeout(onTimeout, 500);
};

var heavy = singleton(heavyInitializer);

console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");

heavy(function(inst) {
  console.log("Access 1");
  console.log("Current property value: " + inst.property);
  console.log("Let's reassign this property");
  inst.property = "new value";
});

heavy(function(inst) {
  console.log("Access 2. You can see callbacks order is preserved.");
  console.log("Current property value: " + inst.property);
});

console.log("We made it to the end of the file. Instance is not ready yet.");

それを切らなかった他のシングルトンの答えによる試練と苦難を通して、私はこれと非常に似た結果のコードを見つけました。
mheyman 2014

何らかの理由で、これが私にとって意味のある唯一の答えです。他の答えはすべて、3人の男性がお互いに肩を再帰的に登ることによって4人の高さの壁を登ろうとするgoon showエピソードを思い出させます。
Tim Ogilvy 2014年

コールバックスタッキングは本当に必要なものです!ありがとう!!
Tim Ogilvy 2014年

このアプローチでは、実際にはシングルトンが次のように提供されることはありません。singleton(singletonInitializer)!== singleton(singletonInitializer)これらは2つの異なるインスタンスです。返された結果の関数は、インスタンスにコールバックを追加するために使用できますが、このタイプのインスタンスを1つだけ作成できることを厳密に指定していません。これがシングルトンの要点です。
オーウェン

6

この例は、JavaScriptパターンから取得しました。コーディングパターンとデザインパターンを使用してより良いアプリケーションを構築するStoyan Stefanovの本によると、singltoneオブジェクトのような単純な実装クラスが必要な場合は、次のように即時関数を使用できます。

var ClassName;

(function() {
    var instance;
    ClassName = function ClassName() {
        //If private instance variable already initialized return reference
        if(instance) {
            return instance;   
        }
        //If instance does not created save pointer of original reference
        //to private instance variable. 
        instance = this;

        //All constructor initialization will be here
        // i.e.: 
        this.someProperty = 0;
        this.someMethod = function() {
            //Some action here
        };
    };
}());

また、次のテストケースでこの例を確認できます。

//Extending defined class like Singltone object using new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
//Extending defined class like Singltone object using new prototype property
ClassName.prototype.everything = true; 
var obj_2 = new ClassName();

//Testing does this two object pointing to same instance
console.log(obj_1 === obj_2); //Result is true, it points to same instance object

//All prototype properites work
//no matter when they were defined
console.log(obj_1.nothing && obj_1.everything 
            && obj_2.nothing && obj_2.everything); //Result true


//Values of properties which is defined inside of constructor
console.log(obj_1.someProperty);// output 0
console.log(obj_2.someProperty);// output 0 
//Changing property value 
obj_1.someProperty = 1;

console.log(obj_1.someProperty);// output 1
console.log(obj_2.someProperty);// output 1

console.log(obj_1.constructor === ClassName); //Output true 

このアプローチはすべてのテストケースに合格しますが、プロトタイプ拡張が使用されるとプライベート静的実装は失敗し(修正は可能ですが、簡単ではありません)、インスタンスがパブリックに公開されるためあまり推奨されないパブリック静的実装です。

jsFiddlyデモ。


5

私はJavaScriptでプログラムする最もクリーンな方法を見つけたと思いますが、想像力が必要になります。このアイデアは、「JavaScriptの良い部分」という本の実用的な手法から得られました。

newキーワードを使用する代わりに、次のようなクラスを作成できます。

function Class()
{
    var obj = {}; // Could also be used for inheritence if you don't start with an empty object.

    var privateVar;
    obj.publicVar;

    obj.publicMethod= publicMethod;
    function publicMethod(){} 

    function privateMethod(){} 

    return obj;
}

上記のオブジェクトをインスタンス化するには、次のように言います。

var objInst = Class(); // !!! NO NEW KEYWORD

この作業方法を念頭に置いて、次のようなシングルトンを作成できます。

ClassSingleton = function()
{
    var instance= null;

    function Class() // This is the class like the above one
    {
        var obj = {};
        return obj;
    }

    function getInstance()
    {
        if( !instance )
            instance = Class(); // Again no new keyword;

        return instance;
    }   

    return { getInstance : getInstance };

}();

これで、次の呼び出しでインスタンスを取得できます

var obj = ClassSingleton.getInstance();

完全な「クラス」にさえアクセスできないので、これは最も近い方法だと思います。


ただし、この手法では、複数のインスタンスを使用できます。それは適切ではありません。
nicolascolman 2017年

1
私はそうは思わないでしょう、あなたはgetInstanceを経由せずにクラスにアクセスすることさえできません。詳しく説明してもらえますか?
David

David Maes申し訳ありませんが、2番目の例の検証には気づきませんでした。謝罪します。
nicolascolman 2017年

4

@CMSと@zzzzBovはどちらもすばらしい答えを出しましたが、シングルトンパターンが一般的であったPHP / Zend Frameworkからのnode.js開発に移行したことに基づいて、独自の解釈を追加します。

次のコメント付きのコードは、次の要件に基づいています。

  • 関数オブジェクトのインスタンスを1つだけインスタンス化できます
  • インスタンスは公開されておらず、パブリックメソッドを介してのみアクセスできます
  • コンストラクタは公開されておらず、インスタンスがまだない場合にのみインスタンス化できます
  • コンストラクターの宣言では、プロトタイプチェーンの変更を許可する必要があります。これにより、コンストラクタは他のプロトタイプから継承し、インスタンスに「パブリック」メソッドを提供できます

私のコードは@zzzzBovのコードに非常に似ていますが、コンストラクタにプロトタイプチェーンを追加し、PHPまたは同様の言語から来た人が従来のOOPをJavascriptのプロトタイプの性質に変換するのに役立つコメントを追加しました。「最も単純」ではないかもしれませんが、私はそれが最も適切であると信じています。

// declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
    "use strict";
    // 'instance' and 'constructor' should not be availble in a "public" scope
    // here they are "private", thus available only within 
    // the scope of the self-executing anonymous function
    var _instance=null;
    var _constructor = function (name) {
        this.name = name || 'default';
    }

    // prototypes will be "public" methods available from the instance
    _constructor.prototype.getName = function () {
        return this.name;
    }

    // using the module pattern, return a static object
    // which essentially is a list of "public static" methods
    return {
        // because getInstance is defined within the same scope
        // it can access the "private" 'instance' and 'constructor' vars
        getInstance:function (name) {
            if (!_instance) {
                console.log('creating'); // this should only happen once
                _instance = new _constructor(name);
            }
            console.log('returning');
            return _instance;
        }
    }

})(); // self execute

// ensure 'instance' and 'constructor' are unavailable 
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined

// assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated

// ensure 'a' and 'b' are truly equal
console.log(a === b); // true

console.log(a.getName()); // "first"
console.log(b.getName()); // also returns "first" because it's the same instance as 'a'

技術的には、@ CMSによって提供されるコードで適切に示されているように、自己実行匿名関数自体がシングルトンです。ここでの唯一の問題は、コンストラクター自体が匿名の場合、コンストラクターのプロトタイプチェーンを変更できないことです。

Javascriptでは、「パブリック」および「プライベート」の概念は、PHPまたはJavaの場合のように適用されないことに注意してください。ただし、Javascriptの機能スコープの可用性に関するルールを活用することで、同じ効果を実現しています。


コードから複数のインスタンスを作成できますvar a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
。– zzzzBov

@zzzzBov:Fiddleでエラーが発生しました:jsfiddle.net/rxMu8
cincodenada

4

なぜだれもこれを取り上げなかった理由はわかりませんが、次のようにできます。

var singleton = new (function() {
  var bar = 123

  this.foo = function() {
    // whatever
  }
})()

これは、getInstanceメソッドをスキップしてより単純なソリューションを取得するための適切な方法のようです。ただし、ファイルが解析されるとすぐにシングルトンが実行されることに注意してください。つまり、DOMリスナーは$(document).ready関数でラップする必要があります
HoffZ

4

最も明確な答えは、Addy Osmani著の「JavaScriptのデザインパターンの学習」の本の答えです。

var mySingleton = (function () {
 
  // Instance stores a reference to the Singleton
  var instance;
 
  function init() {
 
    // Singleton
 
    // Private methods and variables
    function privateMethod(){
        console.log( "I am private" );
    }
 
    var privateVariable = "Im also private";
 
    var privateRandomNumber = Math.random();
 
    return {
 
      // Public methods and variables
      publicMethod: function () {
        console.log( "The public can see me!" );
      },
 
      publicProperty: "I am also public",
 
      getRandomNumber: function() {
        return privateRandomNumber;
      }
 
    };
 
  };
 
  return {
 
    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function () {
 
      if ( !instance ) {
        instance = init();
      }
 
      return instance;
    }
 
  };
 
})();


3

ES7が必要ですが、これが最も簡単でクリーンで直感的な方法だと思います。

export default class Singleton {

  static instance;

  constructor(){
    if(instance){
      return instance;
    }

    this.state = "duke";
    this.instance = this;
  }

}

ソースコードは以下からです:adam-bien.com


これは完全に間違っており、呼び出し時にエラーが発生ますnew Singleton()
UtkarshPramodGupta

2

これの何が問題になっていますか?

function Klass() {
   var instance = this;
   Klass = function () { return instance; }
}

Test = Klass; t1 = new Test(); t2 = new Test();-クラスの名前を変更したり、別の名前空間を選択したりする機会はありません。
zzzzBov

2

5枚のコインを入れてもいいですか。コンストラクタ関数があります。

var A = function(arg1){
  this.arg1 = arg1  
};

私がする必要があるのは、このCFによって作成されるすべてのオブジェクトが同じになることだけです。

var X = function(){
  var instance = {};
  return function(){ return instance; }
}();

テスト

var x1 = new X();
var x2 = new X();
console.log(x1 === x2)

2

使用しているので、次は、最も簡単なSingletonパターンであることを私が見つけた新しいオペレータが行い、これは、オブジェクトリテラルを返す必要がなくなり、関数内ですぐにご利用いただけます:

var singleton = new (function () {

  var private = "A private value";
  
  this.printSomething = function() {
      console.log(private);
  }
})();

singleton.printSomething();


2

これは、JavaScriptでシングルトンパターンを説明する簡単な例です。

 var Singleton=(function(){
      var instance;
      var init=function(){
           return {
             display:function(){
             alert("This is a Singleton patern demo");
              }
            };
           }; 
            return {
              getInstance:function(){
                   if(!instance){
                     alert("Singleton check");
                      instance=init();
                       }
               return instance;
             }
         };

    })();

   // In this call first display alert("Singleton check")
  // and then alert("This is a Singleton patern demo");
  // It means one object is created

    var inst=Singleton.getInstance();
    inst.display();

    // In this call only display alert("This is a Singleton patern demo")
   //  it means second time new object is not created, 
   //  it uses the already created object 

    var inst1=Singleton.getInstance();
    inst1.display();

1

私はいくつかのシングルトンが必要でした:

  • 遅延初期化
  • 初期パラメータ

これが私が思いついたものです:

createSingleton ('a', 'add', [1, 2]);
console.log(a);

function createSingleton (name, construct, args) {
    window[name] = {};
    window[construct].apply(window[name], args);
    window[construct] = null;
}

function add (a, b) {
    this.a = a;
    this.b = b;
    this.sum = a + b;
}
  • これが機能するためには、argsは配列でなければなりません。したがって、空の変数がある場合は、[]を渡してください。

  • 関数でウィンドウオブジェクトを使用しましたが、パラメーターを渡して独自のスコープを作成することもできました

  • 名前と構成パラメーターは、window []が機能するための単なるStringですが、いくつかの単純な型チェックでは、window.nameとwindow.constructも可能です。


1

この方法については、クラスが再び新しいことはできないことを保証するだけです。

これにより、instanceofop を使用できます。また、プロトタイプチェーンを使用してクラスを継承できます。これは通常のクラスですが、新しいインスタンスを作成することはできません。getInstance

function CA()
{
    if(CA.instance)
    {
        throw new Error('can not new this class');
    }else{
        CA.instance = this;
    }

}
/**
 * @protected
 * @static
 * @type {CA}
 */
CA.instance = null;
/** @static */
CA.getInstance = function()
{
    return CA.instance;
}

CA.prototype = 
/** @lends CA#*/
{
    func: function(){console.log('the func');}
}
// initilize the instance
new CA();

// test here
var c = CA.getInstance()
c.func();
console.assert(c instanceof CA)
// this will failed
var b = new CA();

instanceメンバーを公​​開したくない場合は、クロージャーに入れてください。


1

以下は、シングルトンパターンを実装するためのウォークスルーのスニペットです。これはインタビューの過程で私に起こりました、そして私はどこかでこれを捉えるべきだと感じました。

/*************************************************
   *     SINGLETON PATTERN IMPLEMENTATION          *
   *************************************************/

  //since there are no classes in javascript, every object is technically a singleton
  //if you don't inherit from it or copy from it.
  var single = {};
  //Singleton Implementations
  //Declaring as a Global Object...you are being judged!


  var Logger = function() {
    //global_log is/will be defined in GLOBAL scope here
    if(typeof global_log === 'undefined'){
      global_log = this;
    }
    return global_log;
  };


  //the below 'fix' solves the GLOABL variable problem but
  //the log_instance is publicly available and thus can be 

  //tampered with.
  function Logger() {
    if(typeof Logger.log_instance === 'undefined'){
      Logger.log_instance = this;
    }


    return Logger.log_instance;
   };


  //the correct way to do it to give it a closure!


  function logFactory() {
    var log_instance; //private instance
    var _initLog = function() { //private init method
      log_instance = 'initialized';
      console.log("logger initialized!")
    }
    return {
      getLog : function(){ //the 'privileged' method 
        if(typeof log_instance === 'undefined'){
          _initLog();
        }
        return log_instance;
      }
    };
  }

  /***** TEST CODE ************************************************
  //using the Logger singleton
  var logger = logFactory();//did i just gave LogFactory a closure?
  //create an instance of the logger
  var a = logger.getLog();
  //do some work
  //get another instance of the logger
  var b = logger.getLog();


  //check if the two logger instances are same?
  console.log(a === b); //true
  *******************************************************************/

同じことが私の要旨のページにあります


1
function Unicode()
  {
  var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
  //Loop through code points
  while (i < max) {
    //Convert decimal to hex value, find the character, then pad zeroes to the codepoint
    unicode[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
    i = i + 1;
    }

  //Replace this function with the resulting lookup table
  Unicode = unicode;
  }

//Usage
Unicode();
//Lookup
Unicode["%"]; //returns 0025

1

これもシングルトンじゃないですか?

function Singleton() {
    var i = 0;
    var self = this;

    this.doStuff = function () {
        i = i + 1;
        console.log( 'do stuff',i );
    };

    Singleton = function () { return self };
    return this;
}

s = Singleton();
s.doStuff();

1

以下のTypeScriptの例のように、デコレータを使用してそれを行うことができます。

class YourClass {

    @Singleton static singleton() {}

}

function Singleton(target, name, descriptor) {
    var instance;
    descriptor.value = () => {
        if(!instance) instance = new target;
        return instance;
    };
}

次に、次のようにシングルトンを使用します。

var myInstance = YourClass.singleton();

この記事の執筆時点では、JavaScriptエンジンでデコレーターをすぐに使用することはできません。JavaScriptランタイムでデコレーターを実際に有効にするか、BabelやTypeScriptなどのコンパイラーを使用する必要があります。

また、シングルトンインスタンスは「レイジー」で作成されます。つまり、初めて使用するときにのみ作成されます。


1

モジュールパターン:「より読みやすいスタイル」。どのメソッドがパブリックで、どのメソッドがプライベートであるかを簡単に確認できます

var module = (function(_name){
   /*Local Methods & Values*/
   var _local = {
      name : _name,
      flags : {
        init : false
      }
   }

   function init(){
     _local.flags.init = true;
   }

   function imaprivatemethod(){
     alert("hi im a private method");
   }

   /*Public Methods & variables*/

   var $r = {}; //this object will hold all public methods.

   $r.methdo1 = function(){
       console.log("method1 call it");
   }

   $r.method2 = function(){
      imaprivatemethod(); //calling private method
   }

   $r.init = function(){
      inti(); //making init public in case you want to init manually and not automatically
   }

   init(); //automatically calling init method

   return $r; //returning all publics methods

})("module");

今、あなたはパブリックメソッドを使うことができます

module.method2(); //->パブリックメソッドアラートでプライベートメソッドを呼び出しています( "こんにちはプライベートメソッド")

http://jsfiddle.net/ncubica/xMwS9/


1

シングルトン:

クラスにインスタンスが1つしかないことを確認し、インスタンスへのグローバルなアクセスポイントを提供します。

シングルトンパターンは、特定のオブジェクトのインスタンスの数を1つに制限します。この単一のインスタンスはシングルトンと呼ばれます。

  • 一意のインスタンスを返すgetInstance()を定義します。
  • インスタンスオブジェクトの作成と管理を担当します。

Singletonオブジェクトは、即時の無名関数として実装されます。この関数は、角かっこで囲み、さらに2つの角かっこを続けて、すぐに実行されます。名前がないため、匿名と呼ばれます。

サンプルプログラム、

var Singleton = (function () {
    var instance;
 
    function createInstance() {
        var object = new Object("I am the instance");
        return object;
    }
 
    return {
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();
 
function run() {
 
    var instance1 = Singleton.getInstance();
    var instance2 = Singleton.getInstance();
 
    alert("Same instance? " + (instance1 === instance2));  
}

run()


1

私にとって最もシンプル/クリーンなということは、Javaバージョンのディスカッションでよく議論されているように、単に理解し、口笛を吹かないことも意味します。

Javaでシングルトンパターンを実装する効率的な方法は何ですか?

私の観点からそこに最も簡単で/最もきれいに合う答えは:

https://stackoverflow.com/a/70824/1497139

そして、それはJavaScriptに部分的にしか翻訳できません。JavaScriptの違いは次のとおりです。

  • コンストラクターをプライベートにすることはできません
  • クラスは宣言されたフィールドを持つことができません

しかし、最新のECMA構文を考えると、次のように近づけることができます。

JavaScriptクラスの例としてのシングルトンパターン

 class Singleton {

  constructor(field1,field2) {
    this.field1=field1;
    this.field2=field2;
    Singleton.instance=this;
  }

  static getInstance() {
    if (!Singleton.instance) {
      Singleton.instance=new Singleton('DefaultField1','DefaultField2');
    }
    return Singleton.instance;
  }
}

使用例

console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);

結果の例

DefaultField1
DefaultField2

1
function Once() {
    return this.constructor.instance || (this.constructor.instance = this);
}

function Application(name) {
    let app = Once.call(this);

    app.name = name;

    return app;
}

クラスに参加している場合:

class Once {
    constructor() {
        return this.constructor.instance || (this.constructor.instance = this);
    }
}

class Application extends Once {
    constructor(name) {
        super();

        this.name = name;
    }
}

テスト:

console.log(new Once() === new Once());

let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');

console.log(app1 === app2);
console.log(app1.name); // Barfoo

1

クラスを使用する場合:

class Singleton {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    if(this.constructor.instance)
      return this.constructor.instance;
    this.constructor.instance = this;
  }
}
let x = new Singleton('s',1);
let y = new Singleton('k',2);

上記の出力は次のようになります。

console.log(x.name,x.age,y.name,y.age) // s 1 s 1

関数を使用してシングルトンを作成する別の方法

function AnotherSingleton (name,age) {
  this.name = name;
  this.age = age;
  if(this.constructor.instance)
    return this.constructor.instance;
  this.constructor.instance = this;
}

let a = new AnotherSingleton('s',1);
let b = new AnotherSingleton('k',2);

上記の出力は次のようになります。

console.log(a.name,a.age,b.name,b.age)// s 1 s 1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.