JavaScriptでシングルトンパターンを実装する最も簡単でクリーンな方法は何ですか?
最も簡単な方法は、単純なオブジェクトリテラルを宣言することだと思います。
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
シングルトンインスタンスにプライベートメンバーが必要な場合は、次のようなことができます。
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accesible here
},
publicMethod2: function () {
}
};
})();
これはと呼ばれています モジュールパターン、基本的に の使用を利用して、オブジェクトのプライベートメンバーをカプセル化できますクロージャ 。
UPDATE:シングルトンオブジェクトの変更を防ぎたい場合は、フリーズすることができます、ES5を使用 Object.freeze
メソッド。
これにより、オブジェクトが不変になり、その構造と値の変更が防止されます。
さらに、ES6を使用している場合は、ESモジュールを使用してシングルトンを簡単に表すことができ、さらにprivate statemodule scopeで変数を宣言することにより:
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
次に、シングルトンオブジェクトをインポートして使用します。
import myInstance from './my-singleton.js'
// ...
最もクリーンなアプローチは次のようなものだと思います:
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();
シングルトンパターンの代替として使用されているモジュールパターンに同意するかどうかはわかりません。私は、シングルトンが完全に不要な場所で使用され、悪用されるのをよく見ました。また、モジュールパターンは、プログラマがそうでなければシングルトンを使用する多くのギャップを埋めると確信していますが、モジュールパターンはnotですシングルトン。
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
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
my other one を参照してください。
通常、シングルトンパターンではないモジュールパターン(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
猫の皮をむくには複数の方法があります:)あなたの好みや特定のニーズに応じて、提案された解決策を適用できます。個人的には、可能な限り(プライバシーが不要な場合)CMSの最初のソリューションを選びます。質問は最も単純でクリーンなものであるため、それが勝者です。あるいは:
var myInstance = {}; // done!
これ(私のブログからの引用)...
var SingletonClass = new function() {
this.myFunction() {
//do stuff
}
this.instance = 1;
}
それはプライベート変数を必要としないため、あまり意味がありません(私のブログの例もそうではありません)ので、ほとんど同じです:
var SingletonClass = {
myFunction: function () {
//do stuff
},
instance: 1
}
このサンプルは Stoyan Stefanovによるコーディングパターンとデザインパターンでより良いアプリケーションを構築するJavaScriptパターン の本から入手しました。
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
このアプローチはすべてのテストケースに合格しますが、プロトタイプ拡張機能を使用するとプライベートな静的実装は失敗しますが(修正は可能ですが、簡単ではありません)、パブリックな静的実装はインスタンスが公開されるため推奨されません。
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();
});
シングルトンは、アプリケーション全体を通じて複数のインスタンスを提供します。初期化は最初の使用まで遅延されます。初期化が高価なオブジェクトを扱うとき、これは本当に大きなことです。高価なのは通常I/Oを意味し、JavaScript I/Oでは常にコールバックを意味します。
instance = singleton.getInstance()
のようなインターフェイスを提供する回答を信頼しないでください。それらはすべてポイントを失います。
インスタンスの準備ができているときにコールバックを実行しないと、イニシャライザーがI/Oを実行するときに機能しません。
ええ、コールバックは常に、オブジェクトインスタンスをすぐに返す関数呼び出しよりもいように見えます。ただし、I/Oを実行する場合、コールバックは必須です。 I/Oを実行したくない場合、インスタンス化はプログラム開始時に実行できるほど安価です。
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);
});
この例では、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.");
JavaScriptでプログラムする最もクリーンな方法を見つけたと思いますが、想像力が必要です。このアイデアは、「javascript the good parts」という本の実用的なテクニックから得たものです。
新しいキーワードを使用する代わりに、次のようなクラスを作成できます。
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();
完全な「クラス」にもアクセスできないため、これが最も近い方法だと思います。
以下はノード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' }
最も明確な答えは、Addy Osmani著の「Learning JavaScript Design Patterns」からの本です。
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;
}
};
})();
@CMSと@zzzzBovはどちらも素晴らしい答えを与えましたが、シングルトンパターンが一般的だったPHP/Zend Frameworkから重いnode.js開発に移行したことに基づいて、独自の解釈を追加するだけです。
以下のコメント文書化されたコードは、次の要件に基づいています。
私のコードは、プロトタイプチェーンをコンストラクターに追加したことと、PHPまたは同様の言語が従来のOOPをJavascriptに変換するのに役立つコメントを追加したことを除いて、@ zzzzBovに非常に似ていますプロトタイプの性質。それは「最も単純」ではないかもしれませんが、私はそれが最も適切であると信じています。
// 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 singleton = new (function() {
var bar = 123
this.foo = function() {
// whatever
}
})()
5枚のコインを入れてもいいですか? exのコンストラクター関数があります。
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)
これの何が問題になっていますか?
function Klass() {
var instance = this;
Klass = function () { return instance; }
}
これはJavaスクリプトのシングルトンパターンを説明する簡単な例です。
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();
new演算子を使用すると、関数内でthisがすぐに使用可能になり、オブジェクトリテラルを返す必要がなくなるため、以下が最も簡単なシングルトンパターンであることがわかりました。
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
ES7が必要ですが、これは最もシンプル/クリーンで最も直感的な方法だと思います。
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
ソースコードは次のとおりです。 adam-bien.com
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などのコンパイラーを使用する必要があります。
また、シングルトンインスタンスは「レイジー」に作成されます。つまり、初めて使用する場合にのみ作成されます。
以下は、シングルトンパターンを実装するためのウォークスルーの抜粋です。これはインタビューの過程で私に起こり、どこかでこれを捉えるべきだと感じました。
/*************************************************
* 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
*******************************************************************/
同じことは私の Gist ページで見つけることができます
私はいくつかのシングルトンが必要でした:
そして、これは私が思いついたものでした:
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はこれが機能するために配列である必要があるため、空の変数がある場合は[]を渡すだけです
関数でウィンドウオブジェクトを使用しましたが、パラメーターを渡して独自のスコープを作成できました。
nameおよび構造パラメータは、window []が機能するための文字列のみですが、いくつかの単純な型チェックでは、window.nameおよびwindow.constructも可能です。
この方法はどうですか、クラスが再び新しくならないことを保証してください。
これにより、instanceof
opを使用できます。また、プロトタイプチェーンを使用してクラスを継承できます。これは通常のクラスですが、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つだけあることを確認し、グローバルアクセスポイントを提供します。
シングルトンパターンは、特定のオブジェクトのインスタンスの数を1つに制限します。この単一のインスタンスはシングルトンと呼ばれます。
シングルトンオブジェクトは、即時の匿名関数として実装されます。関数は、角かっこで囲み、さらに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()
モジュールパターン:「読みやすいスタイル」。どのメソッドがパブリックで、どのメソッドがプライベートであるかを簡単に確認できます
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(); //-> publicメソッドalert( "hi im a private method")を介してprivateメソッドを呼び出しています
これもシングルトンではありませんか?
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();
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
私は、Singletonとモジュールパターンの組み合わせを使用し、グローバルNSチェックによる初期化時の分岐をクロージャーにラップして使用します。シングルトンの初期化後に環境が変更されない場合。すぐに呼び出されるobject-literalを使用して、一定期間持続するユーティリティで満たされたモジュールを返すことは問題ありません。私は依存関係を渡さず、自分の小さな世界内でシングルトンを呼び出すだけです-唯一の目標は、イベントのバインド/バインド解除のためのユーティリティモジュールを作成することです(この場合、デバイスの向き/向きの変更も機能します)。
window.onload = ( function( _w ) {
console.log.apply( console, ['it', 'is', 'on'] );
( {
globalNS : function() {
var nameSpaces = ["utils", "eventUtils"],
nsLength = nameSpaces.length,
possibleNS = null;
outerLoop:
for ( var i = 0; i < nsLength; i++ ) {
if ( !window[nameSpaces[i]] ) {
window[nameSpaces[i]] = this.utils;
break outerLoop;
};
};
},
utils : {
addListener : null,
removeListener : null
},
listenerTypes : {
addEvent : function( el, type, fn ) {
el.addEventListener( type, fn, false );
},
removeEvent : function( el, type, fn ) {
el.removeEventListener( type, fn, false );
},
attachEvent : function( el, type, fn ) {
el.attachEvent( 'on'+type, fn );
},
detatchEvent : function( el, type, fn ) {
el.detachEvent( 'on'+type, fn );
}
},
buildUtils : function() {
if ( typeof window.addEventListener === 'function' ) {
this.utils.addListener = this.listenerTypes.addEvent;
this.utils.removeListener = this.listenerTypes.removeEvent;
} else {
this.utils.attachEvent = this.listenerTypes.attachEvent;
this.utils.removeListener = this.listenerTypes.detatchEvent;
};
this.globalNS();
},
init : function() {
this.buildUtils();
}
} ).init();
}( window ) );
Javascriptのシングルトンは、モジュールパターンとクロージャを使用して実現されます。以下は自明なコードです-
// singleton example.
var singleton = (function() {
var instance;
function init() {
var privateVar1 = "this is a private variable";
var privateVar2 = "another var";
function pubMethod() {
//accessing private variables from inside.
console.log(this.privateVar1);
console.log(this.privateVar2);
console.log("inside of a public method");
};
}
function getInstance() {
if (!instance) {
instance = init();
}
return instance;
};
return {
getInstance: getInstance
}
})();
var obj1 = singleton.getInstance();
var obj2 = singleton.getInstance();
cnosole.log(obj1===obj2); //check for type and value.
「ブラウザで」と言わなかった。それ以外の場合は、 NodeJSモジュール を使用できます。これらは require
の各呼び出しで同じ です。基本的な例:
Foo.jsの内容:
const circle = require('./circle.js'); console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);
Circle.jsのコンテンツ:
const PI = Math.PI; exports.area = (r) => PI * r * r; exports.circumference = (r) => 2 * PI * r;
circle.PI
はエクスポートされないため、アクセスできないことに注意してください。
これはブラウザでは機能しませんが、シンプルでクリーンです。
私にとって最もシンプル/クリーンなのは、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
主な鍵は、この背後にあるアンダータントクロージャーの重要性です。したがって、内部関数内のプロパティもクロージャーの助けを借りてプライベートになります。
var Singleton = function(){varインスタンス;
function init() {
function privateMethod() {
console.log("private via closure");
}
var privateVariable = "Private Property";
var privateRandomNumber = Math.random();// this also private
return {
getRandomNumber: function () { // access via getter in init call
return privateRandomNumber;
}
};
};
return {
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
};
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
すべてのnew
の実行で同じインスタンスを返すことができます-
function Singleton() {
// lazy
if (Singleton.prototype.myInstance == undefined) {
Singleton.prototype.myInstance = { description: "I am the instance"};
}
return Singleton.prototype.myInstance;
}
a = new Singleton();
b = new Singleton();
console.log(a); // { description: "I am the instance"};
console.log(b); // { description: "I am the instance"};
console.log(a==b); // true