Самый простой / чистый способ реализации синглтона в JavaScript?
каков самый простой / чистый способ реализации одноэлементного шаблона в JavaScript?
30 ответов:
Я думаю, самый простой способ-объявить простой литерал объекта:
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 () { } }; })();
Это называется the модуль pattern, это в основном позволяет инкапсулировать частные члены на объекте, воспользовавшись использованием закрытие.
Я думаю, что самый чистый подход-это что-то вроде:
var SingletonClass = (function(){ function SingletonClass() { //do stuff } var instance; return { getInstance: function(){ if (instance == null) { instance = new SingletonClass(); // Hide the constructor so the returned objected can't be new'd... instance.constructor = null; } return instance; } }; })();
после этого вы можете вызвать функцию как
var test = SingletonClass.getInstance();
Я не уверен, что согласен с шаблоном модуля, используемым в качестве замены для одноэлементного шаблона. Я часто видел синглтоны, используемые и злоупотребляемые в местах, где они совершенно не нужны, и я уверен, что шаблон модуля заполняет много пробелов, где программисты в противном случае использовали бы синглтон, однако шаблон модуля не одноплодной.
модуль рисунка:
var foo = (function () { "use strict"; function aPrivateFunction() {} return { aPublicFunction: function () {...}, ... }; }());
все инициализированное в шаблоне модуля происходит, когда
Foo
is объявленный. Кроме того, шаблон модуля можно использовать для инициализации конструктора, который затем может быть создан несколько раз. Хотя шаблон модуля является правильным инструментом для многих заданий, он не эквивалентен одиночному элементу.паттерн Singleton:
краткая формадлинная форма, используя шаблон модуля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; }());
в обеих версиях шаблона 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
существует несколько способов освежевать кошку :) в зависимости от вашего вкуса или конкретной потребности вы можете применить любое из предложенных решений. Я лично иду на первое решение CMS, когда это возможно (когда вам не нужна конфиденциальность). Поскольку вопрос был о самом простом и чистом, это победитель. Или даже:
var myInstance = {}; // done!
Это (цитата из моего блога) ...
var SingletonClass = new function() { this.myFunction() { //do stuff } this.instance = 1; }
не имеет большого смысла (мой пример блога тоже), потому что он не нуждается в каких-либо частных Варс, так что это почти то же самое, что:
var SingletonClass = { myFunction: function () { //do stuff }, instance: 1 }
Я осуждаю свой ответ, см. мой другой.
обычно шаблон модуля (см. ответ CMS), который не является одноэлементным шаблоном, достаточно хорош. Однако одной из особенностей синглтона является то, что его инициализация задерживается до тех пор, пока объект не понадобится. В шаблоне модуля отсутствует эта функция.
мое предложение (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
Я получил этот пример от Шаблоны JavaScript Создание лучших приложений с помощью шаблонов кодирования и проектирования Стоян Стефанов's Книга в случае, если вам нужен какой-то простой класс реализации, как однотонный объект вы можете использовать немедленную функцию следующим образом:
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 действительно уродливы в использовании. Глобальные переменные дадут вам один экземпляр через все приложение тоже без всех этих обратных вызовов, шаблон модуля мягко скрывает внутренние за интерфейсом. См. ответ @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(); });
объяснение:
синглтоны дать вам больше, чем просто один экземпляр через все приложение: их инициализация задерживается до первого использования. Это действительно большая вещь, когда вы имеете дело с объектами, инициализация которых стоит дорого. Дорогие, как правило, средства ввода-вывода и в JavaScript ввода/вывода всегда означает обратных вызовов.
не доверяйте ответы, которые дают вам интерфейс, как
instance = singleton.getInstance()
, они все упускают суть.если они не принимают обратный вызов для запуска, когда экземпляр готов, то они не будут работать, когда инициализатор выполняет ввод-вывод.
да, обратные вызовы всегда выглядят уродливее, чем вызов функции, которая сразу возвращает экземпляр объекта. Но опять же: когда вы делаете 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, инициализация с помощью ввода / вывода:
setTimeout
подделывает некоторые дорогостоящие операции ввода-вывода. Это иллюстрирует, почему синглеты в В 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();
Я думаю, что это самый аккуратный способ, так как полный "класс" даже не доступен.
@CMS и @zzzzBov оба дали замечательные ответы, но просто добавить свою собственную интерпретацию, основанную на моем перемещении в тяжелый узел.разработка js из PHP / Zend Framework, где были распространены одноэлементные шаблоны.
следующий код, документированный комментариями, основан на следующих требованиях:
- один и только один экземпляр объекта функции может быть создан
- экземпляр не является общедоступным и может быть доступен только через публичный метод
- конструктор не является общедоступным и может быть создан только в том случае, если экземпляр еще не доступен
- объявление конструктора должно позволять изменять его цепочку прототипов. Это позволит конструктору наследовать от других прототипов и предлагать "общедоступные" методы для экземпляра
мой код очень похож на @zzzzBov, за исключением того, что я добавил цепочку прототипов в конструктор и больше комментариев, которые должно помочь тем, кто приходит из PHP или аналогичного языка перевести традиционный ООП на Javascripts прототипической природы. Это может быть не самый "простой", но я считаю, что это самый правильный.
// 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 понятия "public" и "private" не применяются так, как в PHP или Java. Но мы достигли того же эффекта, используя правила доступности функциональной области Javascript.
Не знаю, почему никто не поднял эту тему, но вы могли бы просто сделать:
var singleton = new (function() { var bar = 123 this.foo = function() { // whatever } })()
на
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
самый ясный ответ должен быть этим из книги Learning JavaScript Design Patterns by Addy Osmani.
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; } }; })();
могу ли я положить свои 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)
следующие работы в узле 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' }
Я нашел следующее, чтобы быть самый простой паттерн Singleton, потому что с помощью новая оператор этой сразу же доступны в функции, устраняя необходимость возвращать литерал объекта:
var singleton = new (function () { var private = "A private value"; this.printSomething = function() { console.log(private); } })(); singleton.printSomething();
Мне нужно было несколько синглетов с:
- ленивая инициализация
- исходные параметры
и вот что я придумал:
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 В функции, но я мог бы передать параметр, чтобы создать свою собственную область
имя и построить параметры - это только строка для работы window [], но с некоторой простой проверкой типа, window.name и окно.построить также возможно.
что в этом плохого?
function Klass() { var instance = this; Klass = function () { return instance; } }
как насчет этого способа, просто застраховать класс не может новый снова.
таким образом, вы можете использовать
instanceof
op, кроме того,вы можете использовать цепочку прототипов для наследования класса, это обычный класс,но не может его создать, если yuu хочет получить экземпляр просто используйте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
- члены, просто положите его в закрытие.
ниже приведен фрагмент из моей прогулки, чтобы реализовать одноэлементный шаблон. Это пришло мне в голову во время процесса интервью, и я чувствовал, что должен запечатлеть это где-то.
/************************************************* * 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 *******************************************************************/
то же самое можно найти на моем суть страница
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
разве это не синглтон тоже?
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();
вы можете сделать это с декораторами, как в этом примере ниже для 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.
также обратите внимание, что одноэлементный экземпляр создается "ленивым", т. е. он создается только тогда, когда вы используете его для первый раз.
шаблон модуля: в "более читаемом стиле". Вы можете легко увидеть, какие методы являются публичными, а какие-частными
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");
теперь вы можете использовать методы publics, такие как
модуль.method2 (); / / - > я вызываю частный метод через предупреждение публичного метода ("hi im a private method")
Синглтон:
убедитесь, что класс имеет только один экземпляр, и предоставляет глобальную точку доступа к нему.
одноэлементный шаблон ограничивает число экземпляров конкретного объекта только одним. Этот единственный экземпляр называется синглтоном.
- определяет getInstance() который возвращает уникальный экземпляр.
- ответственность за создание и управление объект.
одноэлементный объект реализуется как непосредственная анонимная функция. Функция выполняется немедленно, заключая ее в скобки, за которыми следуют две дополнительные скобки. Он называется анонимным, потому что у него нет имени.
Пример Программы,
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()
вот простой пример, чтобы объяснить одноэлементный шаблон в Java script.
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();
Мне нравится использовать комбинацию Синглтона с шаблоном модуля, ветвление init-time с глобальной проверкой NS, обернутой в закрытие. В случае, когда среда не будет меняться после инициализации синглтона; использование немедленно вызываемого объектного литерала для возврата модуля, полного утилит, которые будут сохраняться в течение некоторого времени, должно быть прекрасным. Я не передаю никаких зависимостей, просто вызываю синглтонов в их собственном маленьком мире - единственная цель создание модуля утилит для привязки / развязки событий (в этом случае также могут работать изменения ориентации / ориентации устройства).
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 ) );
вы не сказали "в браузере". В противном случае, вы можете использовать NodeJS модули. Эти одинаковы для всех
require
вызов. Простой пример:содержание foo.js:
const circle = require('./circle.js'); console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);
содержание круга.js:
const PI = Math.PI; exports.area = (r) => PI * r * r; exports.circumference = (r) => 2 * PI * r;
обратите внимание, что вы не можете получить доступ
circle.PI
, так как она не экспортируется.хотя это не работает в браузере, это просто и чисто.
главным образом ключ Undertand важность закрытия позади this.So свойство даже внутри внутренней функции будет частным с помощью закрытия.
var Singleton = функция () { var instance;
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; } };
};
синглтон в 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.
Я считаю, что это самый простой / чистый и интуитивно понятный способ, хотя он требует ES7:
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
исходный код от:adam-bien.com