Самый простой / чистый способ реализовать синглтон в JavaScript?

Какой самый простой / чистый способ реализовать шаблон синглтона в JavaScript?

46 ответов

Решение

Я думаю, что самый простой способ - объявить простой объектный литерал:

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

Это называется модульным шаблоном, он в основном позволяет инкапсулировать закрытые элементы в объекте, используя преимущества замыканий.

Я думаю, что самый чистый подход - это что-то вроде:

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

В 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

Или, если вы не хотите, чтобы при создании второго экземпляра возникала ошибка, вы можете просто вернуть последний экземпляр, например:

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"

Я не уверен, что согласен с шаблоном модуля, который используется в качестве замены одноэлементного шаблона. Я часто видел синглтоны, используемые и злоупотребляемые там, где они совершенно не нужны, и я уверен, что шаблон модуля заполняет много пробелов, где программисты иначе использовали бы одиночный код, однако шаблон модуля не является одиночным.

шаблон модуля:

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

В обеих версиях шаблона 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

Если вы используете node.JSтогда вы можете воспользоваться механизмом кеширования node.JS, и все будет так просто, как:

      class Singleton {
    constructor() {
        this.message = 'I am an instance';
    }
}
module.exports = new Singleton();

Обратите внимание , что мы экспортируем не в классе Singletonно экземпляр Singleton().

Node.JS будет кэшировать и повторно использовать один и тот же объект каждый раз, когда это потребуется.

Для получения дополнительной информации, пожалуйста, проверьте: Node.JS и Singleton Pattern.

Следующие работы в узле 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' }

Самый простой / самый чистый для меня означает также простое понимание и никаких наворотов, которые часто обсуждаются в версии обсуждения Java:

Каков эффективный способ реализации одноэлементного шаблона в Java?

Ответ, который, с моей точки зрения, лучше всего подошел бы для этого простейшего / самого чистого:

/questions/42457118/kakov-effektivnyij-sposob-realizatsii-odnoelementnogo-shablona-v-java/42457198#42457198

И его можно только частично перевести на JavaScript. Некоторые различия в Javascript:

  • конструкторы не могут быть частными
  • Классы не могут иметь объявленных полей

Но, учитывая последний синтаксис ECMA, можно приблизиться к следующему:

Шаблон Singleton как пример класса 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

Если вы хотите использовать классы:

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

Я получил этот пример из JavaScript-шаблонов. Создайте лучшие приложения с помощью шаблонов кодирования и дизайна. По книге Стояна Стефанова, если вам нужен какой-то простой класс реализации, такой как объект 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 демо.

Существует более одного способа кожи кошки:) В зависимости от вашего вкуса или конкретной потребности вы можете применить любое из предложенных решений. Лично я по возможности выбираю первое решение CMS (когда вам не нужна конфиденциальность). Поскольку вопрос был о самом простом и чистом, это победитель. Или даже:

var myInstance = {}; // done!

Это (цитата из моего блога) ...

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

не имеет особого смысла (пример моего блога тоже не имеет), потому что ему не нужны частные переменные, так что это почти так же, как:

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

Использование классов ES6 и закрытых статических полей. Вызов новых экземпляров класса Singleton вернет тот же экземпляр. Переменная экземпляра также является закрытой и не может быть доступна вне класса.

      class Singleton {
  // # is a new Javascript feature that denotes private
  static #instance;

  constructor() {
    if (!Singleton.#instance) {
      Singleton.#instance = this
    } 
    return Singleton.#instance
  }

  get() {
    return Singleton.#instance;
  }
}

const a = new Singleton();
const b = new Singleton();
console.log(a.get() === b.get()) // true
console.log(Singleton.instance === undefined) // true

Я не одобряю мой ответ, см. Мой другой.

Обычно шаблон модуля (см. Ответ CMS), который НЕ является одноэлементным, достаточно хорош. Однако одной из особенностей singleton является то, что его инициализация задерживается до тех пор, пока объект не понадобится. В шаблоне модуля отсутствует эта функция.

Мое предложение (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, но вам нужно немного воображения. Я получил эту идею из техники работы в книге "Javascript хорошие части".

Вместо использования нового ключевого слова вы можете создать класс, подобный этому:

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

Я думаю, что это самый удачный способ, так как полный "Класс" даже недоступен.

Короткий ответ:

Поскольку неблокирующая природа JavaScript, Singletons в 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() они все упускают суть.

Если они не принимают обратный вызов для запуска, когда экземпляр готов, то они не будут работать, когда инициализатор выполняет ввод-вывод.

Да, обратные вызовы всегда выглядят хуже, чем вызов функции, которая немедленно возвращает экземпляр объекта. Но опять же: когда вы делаете ввод / вывод, обратные вызовы обязательны. Если вы не хотите выполнять какие-либо операции ввода-вывода, то создание экземпляра достаточно дешево, чтобы сделать это при запуске программы.

Пример 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 подделывает некоторые дорогие операции ввода / вывода. Это показывает, почему синглтонам в 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.");

@CMS и @zzzzBov оба дали замечательные ответы, но просто добавили мою собственную интерпретацию, основанную на том, что я перешел в разработку heavy node.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 понятия "открытый" и "закрытый" не применяются, как в PHP или Java. Но мы достигли того же эффекта, используя правила доступности функциональных возможностей Javascript.

Не знаю, почему никто не поднял это, но вы могли бы просто сделать:

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

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

Вот как я реализую одноэлементный шаблон, используя функции ES6. Да, я знаю, что это не похоже на объектно-ориентированный подход, но я считаю, что этот метод прост в реализации и прост в реализации.

      const Singleton = (() => {
  var _instance = !_instance && new Object('Object created....');
  return () => _instance;
})();

//************************************************************************

var instance1 = Singleton();
var instance2 = Singleton();
console.log(instance1 === instance2); // true

Самым ясным ответом должен стать ответ из книги "Изучение шаблонов проектирования 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;
    }
 
  };
 
})();

Для меня самый чистый способ сделать это:

const singleton = new class {
    name = "foo"
    constructor() {
        console.log(`Singleton ${this.name} constructed`)
    }
}

Используя этот синтаксис, вы уверены, что ваш синглтон будет и останется уникальным. Вы также можете насладиться сладостью синтаксиса класса и использоватьthis как и ожидалось.

(Обратите внимание, что для полей класса требуется узел v12+ или современный браузер.)

Что с этим не так?

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

Я считаю, что это самый простой / чистый и интуитивно понятный способ, хотя он требует ES7:

export default class Singleton {

  static instance;

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

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

}

Исходный код от: adam-bien.com

Я обнаружил, что следующее - это самый простой шаблон Singleton, потому что использование оператора new делает его сразу доступным внутри функции, устраняя необходимость возвращать литерал объекта:

var singleton = new (function () {

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

singleton.printSomething();

Эти знания основаны на том, что я изучаю Java, хотя Java и Javascript разные, концепция Singleton и то, как это делает Java, одинаковы. На мой взгляд, стиль класса из JS чист сам по себе, а неvarинициализация.

      class Singleton {
    // use hashtag which entails that the variable can only be accessed from self scope
    static #instance = null;
    static getInstance() {
        if (this.#instance === null) this.#instance = new Singleton();
        return this.#instance;
    }

    // some class property
    hello = 'world';

    // or initialize the variable in the constructor, depend on your preference
    constructor() {
        // this.hello = 'world';
    }

    /* you can also add parameters on the constructor & getInstance
     * e.g. 
     * static getInstance(param1, param2) {...new Singleton(param1, param2)}
     * constructor(param1, param2) {...}
     */

}




// this is the same code for java and normal way for singleton for class
// just use static so you can get instance


// testing the singleton
var s1,s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();

// you cannot access the property, immediately
if (Singleton.hello === undefined) console.log('getInstance so you can access this');

console.log(s1.hello);
// result: "world"

console.log(s2.hello);
// result: "world"


// set the value of Singleton object
s2.hello = "hi";
    console.log(s1.hello);
    // result: "hi"

    console.log(s2.hello);
    // result: "hi"
// this is just an evidence which means that they are the same even in property level

if (s1 === s2) console.log("S1 & S2 is the same object");
// result: "S1 & S2 is the same object"

// don't use something like `var s1 = new Singleton();`
// this will defeat your purpose of just (1 object), one instance of class

Ниже приведен фрагмент из моей прогулки по реализации шаблона синглтона. Это произошло со мной во время собеседования, и я почувствовал, что должен это где-то запечатлеть.

/*************************************************
   *     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
  *******************************************************************/

то же самое можно найти на моей странице

Синглтон:

Убедитесь, что у класса есть только один экземпляр, и предоставьте ему глобальную точку доступа.

Шаблон Singleton ограничивает количество экземпляров определенного объекта только одним. Этот единственный экземпляр называется синглтоном.

  • определяет getInstance(), который возвращает уникальный экземпляр.
  • отвечает за создание и управление объектом экземпляра.

Объект Singleton реализован как непосредственная анонимная функция. Функция выполняется немедленно, заключив ее в квадратные скобки, за которыми следуют две дополнительные скобки. Он называется анонимным, потому что у него нет имени.

Образец программы,

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-скрипте.

 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();
      let MySingleton = (function () {
  var _instance
  function init() {
    if(!_instance) {
      _instance = { $knew: 1 }
    }
    return _instance
  }
  let publicAPIs = {
    getInstance: function() {
      return init()
    }
  }
  // this prevents customize the MySingleton, like MySingleton.x = 1
  Object.freeze(publicAPIs) 
  // this prevents customize the MySingleton.getInstance(), like MySingleton.getInstance().x = 1
  Object.freeze(publicAPIs.getInstance())
  return publicAPIs
})();
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

Могу ли я положить свои 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)
Другие вопросы по тегам