जावास्क्रिप्ट में सिंगलटन को लागू करने का सबसे सरल / साफ तरीका?


300

जावास्क्रिप्ट में सिंगलटन पैटर्न को लागू करने का सबसे सरल / साफ तरीका क्या है?


15
स्वीकार किए जाते हैं उत्तर के लिए एक सिंगलटन नहीं होने के लिए डाउनवोट। यह सिर्फ एक वैश्विक चर है।
mlibby

5
यह एक टन की जानकारी है, लेकिन वास्तव में विभिन्न जेएस डिजाइन पैटर्न के बीच के अंतर को स्पष्ट करता है। इससे मुझे बहुत मदद मिली: addyosmani.com/resources/essentialjsdesignpatterns/book
जस्टिन

जवाबों:


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

इसे मॉड्यूल पैटर्न कहा गया है , यह मूल रूप से आपको किसी वस्तु पर निजी सदस्यों को बंद करने के लाभ का लाभ उठाने की अनुमति देता है ।

अद्यतन: मैं जोड़ना चाहूंगा कि यदि आप सिंगलटन ऑब्जेक्ट के संशोधन को रोकना चाहते हैं, तो आप इसे ईएस 5 का उपयोग करके फ्रीज कर सकते हैं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?
टाइपऑफ

4
@, हां, पैटर्न का जन्म कक्षा-आधारित ओओपी भाषाओं पर हुआ था-मुझे बहुत सारे कार्यान्वयन याद हैं जिनमें एक स्थैतिक getInstanceविधि शामिल है , और एक निजी कंस्ट्रक्टर- लेकिन IMO, यह एक सिंगलटन ऑब्जेक्ट बनाने का सबसे "सरल" तरीका है जावास्क्रिप्ट में, और अंत में यह एक ही उद्देश्य-एक एकल वस्तु से मिलता है, कि आप फिर से इनिशियलाइज़ नहीं कर सकते (कोई कंस्ट्रक्टर नहीं है, यह सिर्फ एक ऑब्जेक्ट है) -। आपके द्वारा लिंक किए गए कोड के बारे में, इसमें कुछ समस्याएं हैं, स्वैप aऔर bचर घोषणाएं और परीक्षण a === window। चीयर्स।
CMS

15
@ विक्टर - इस तरह की भाषा में "सिंगलटन पैटर्न" देखने के लिए यह अजीब नहीं है। कई ऑब्जेक्ट-ओरिएंटेड भाषाएं वैश्विक चर का उपयोग करती हैं और अभी भी एकल उपयोग में हैं। सिंगलटन केवल इस बात की गारंटी नहीं है कि दी गई कक्षा की केवल एक वस्तु होगी। सिंगलटन में कुछ और विशेषताएं हैं: 1) इसे पहले उपयोग में आरंभीकृत किया जाना चाहिए (जिसका अर्थ है कि न केवल विलंबित आरंभीकरण, बल्कि यह भी गारंटी है कि वस्तु वास्तव में उपयोग करने के लिए तैयार है) 2) यह थ्रेड-सुरक्षित होना चाहिए। मॉड्यूल पैटर्न सिंगलटन पैटर्न के लिए बदला जा सकता है लेकिन केवल ब्राउज़र में (और हमेशा नहीं)।
स्केले

55
यह स्वीकृत उत्तर नहीं होना चाहिए। यह एक सिंगलटन नहीं है! यह सिर्फ एक वैश्विक चर है। दोनों के बीच अंतर की दुनिया है।
mlibby

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.constructor:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
रोब डब्ल्यू

var test = SingletonClass.getInstance () - बहुत साफ या जेएस की तरह नहीं दिखता है। अन्य आत्माएं जो एक नए फू = () के साथ समाप्त होती हैं; b = नया फू (); a === b // true
Matthias

3
पूरे "getInstance" भाग के साथ मेरे लिए कारखाने की तरह खुशबू आ रही है।
लाजोस मेस्सरोस

1
यह एक सिंगलटन नहीं है क्योंकि आप Object.create के साथ इसके कई उदाहरण बना सकते हैं।
AndroidDev

फिडल टूट गया है
हॉफज

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
मैंने कभी भी सिंगलटन के बुरे या अच्छे विचार के बारे में कुछ नहीं कहा। मैंने कहा कि सिंगलटन का आपका कार्यान्वयन इससे कहीं अधिक जटिल है, क्योंकि आपको जावा की सीमाओं को पैटर्न के साथ भ्रमित करना है जैसे कि आप इसे बिल्कुल भी नहीं समझते हैं। जब आप बस जावास्क्रिप्ट में इसके लिए अनाम कार्यों का उपयोग कर सकते हैं, तो निर्माण कार्यों और विधियों को बनाकर रणनीति पैटर्न को लागू करना पसंद है।
एस्लेइजा

11
@Esailija, यह मुझे लगता है जैसे आप सिंगलटन पैटर्न को नहीं समझते हैं। सिंगलटन पैटर्न एक डिज़ाइन पैटर्न है जो किसी क्लास के इंस्टेंटेशन को एक ऑब्जेक्ट में सीमित करता है। var singleton = {}वह परिभाषा फिट नहीं है।
zzzzBov

9
यह केवल उनकी सीमाओं के कारण जावा जैसी भाषाओं पर लागू होता है। var singleton = {}आप जावास्क्रिप्ट में सिंगलटन को कैसे लागू करते हैं
एस्लेइजा

2
@Esailija, "एक प्रोटोटाइप-आधारित प्रोग्रामिंग भाषा में, जहां ऑब्जेक्ट्स का उपयोग किया जाता है लेकिन कक्षाओं का उपयोग नहीं किया जाता है ..." जावास्क्रिप्ट में कक्षाओं की अवधारणा है, ताकि यह लागू न हो।
zzzzBov

3
वैसे। सिंगलटन एक विरोधी पैटर्न है और इसे कभी भी जावास्क्रिप्ट जैसे प्रबंधित सैंडबॉक्स वाले वातावरण में उपयोग नहीं किया जाना चाहिए। misko.hevery.com/2008/08/17/singletons-are-pathological-liars - youtube.com/watch?v=G32acYVd9LY blogs.msdn.com/b/scottdensmore/archive/200/05/05/25/140827.aspx - jalf.dk/blog/2010/03/… - kore-nordmann.de/blog/0103_static_considered_harmful.html - phparch.com/2010/03/03/static-methods.ss-singletons-choose-neither
बेंजामिन

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

या, यदि आप दूसरे उदाहरण के निर्माण पर कोई त्रुटि नहीं चाहते हैं, तो आप अंतिम उदाहरण को वापस कर सकते हैं, जैसे:

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। यह प्रोग्रामिंग भाषाओं में सिर्फ एक नामकरण सम्मेलन है जिसे हम एक अंडरस्कोर के साथ प्रचलित निजी चर नाम देते हैं । मुझे आपके कोड के काम न करने के कारण पर संदेह है कि आप this.instanceइसके बजाय उपयोग कर रहे हैंMyClass.instance
UtkarshPramodGupta

7

एक बिल्ली की त्वचा के लिए एक से अधिक तरीके हैं :) अपने स्वाद या विशिष्ट आवश्यकता के आधार पर आप किसी भी प्रस्तावित समाधान को लागू कर सकते हैं। जब भी संभव हो (जब आपको गोपनीयता की आवश्यकता नहीं हो) मैं व्यक्तिगत रूप से सीएमएस के पहले समाधान के लिए जाता हूं। चूंकि सवाल सबसे सरल और साफ-सुथरा था, इसलिए वह विजेता है। या और भी:

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

मैं अपने जवाब को चित्रित करता हूं, मेरे दूसरे को देखें ।

आमतौर पर मॉड्यूल पैटर्न (सीएमएस का उत्तर देखें) जो सिंगलटन पैटर्न नहीं है, काफी अच्छा है। हालाँकि सिंगलटन की एक विशेषता यह है कि इसके आरंभीकरण में देरी तब तक की जाती है जब तक कि वस्तु की आवश्यकता नहीं होती। मॉड्यूल पैटर्न में इस सुविधा का अभाव है।

मेरा प्रस्ताव (कॉफीस्क्रिप्ट):

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

इसे जावास्क्रिप्ट में संकलित किया गया है:

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

यदि यह आवश्यक नहीं है तो आप मॉड्यूल को क्यों लोड करेंगे? और जब आपको मॉड्यूल को लोड करने की आवश्यकता होती है, तो आप मॉड्यूल को लोड करते हैं, और यह इनिशियलाइज़ करता है।
एस्लेइजा

6

संक्षिप्त जवाब:

क्योंकि जावास्क्रिप्ट की गैर-अवरुद्ध प्रकृति, जावास्क्रिप्ट में सिंग्लेटन्स वास्तव में उपयोग में बदसूरत हैं। वैश्विक चर आपको इन सभी कॉलबैक के बिना भी पूरे एप्लिकेशन के माध्यम से एक उदाहरण देगा, मॉड्यूल पैटर्न धीरे-धीरे इंटरफ़ेस के पीछे आंतरिक छुपाता है। देखिए @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 होता है और जावास्क्रिप्ट 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 ऑपरेशन किए गए हैं। यह दिखाता है कि जावास्क्रिप्ट में सिंगलटन को वास्तव में कॉलबैक की आवश्यकता क्यों है।

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.");

अन्य एकल जवाबों के साथ परीक्षणों और क्लेशों के माध्यम से, जो इसे काट नहीं करते थे, मैं इसके परिणामस्वरूप उल्लेखनीय कोड पर उतरा।
महायान

एक कारण या किसी अन्य के लिए, यह एकमात्र उत्तर है जो मेरे लिए समझ में आता है। अन्य उत्तर मुझे गुंडों के शो के एपिसोड की याद दिलाते हैं, जहां तीन लोग एक दीवार पर चढ़ने की कोशिश करते हैं, जो एक दूसरे पर कंधे से कंधा मिलाकर चढ़ाई करते हैं।
टिम ओगिल्वी

कैलबैक स्टैकिंग वह चीज है जिसकी मुझे वास्तव में आवश्यकता है! धन्यवाद!!
टिम ओगिल्वी

यह दृष्टिकोण वास्तव में आपको कभी भी एक सिंगलटन के रूप में नहीं देता है: सिंगलटन (सिंगलटन इन्युएलाइज़र)! == सिंगलटन (सिंगलटन इंसुलेटर) वे दो अलग-अलग उदाहरण हैं। परिणामी फ़ंक्शन जिसे आप लौटाते हैं, उदाहरण के लिए अधिक कॉलबैक संलग्न करने के लिए उपयोग किया जा सकता है, लेकिन यह कड़ाई से निर्दिष्ट नहीं करता है कि इस प्रकार का केवल एक उदाहरण बनाया जा सकता है। जो एक सिंगलटन का पूरा बिंदु है।
ओवेन

6

मुझे यह उदाहरण दिया गया है कि स्टोअन स्टेफानोव की पुस्तक के पैटर्न और कोडिंग के साथ बेहतर पैटर्न बनाएँ

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

मुझे लगता है कि मुझे जावास्क्रिप्ट में प्रोग्राम करने का सबसे साफ तरीका मिल गया है, लेकिन आपको कुछ कल्पना की आवश्यकता होगी। मुझे यह विचार "अच्छे भागों की जावास्क्रिप्ट" पुस्तक में एक कामकाजी तकनीक से मिला।

नए कीवर्ड का उपयोग करने के बजाय, आप इस तरह एक वर्ग बना सकते हैं:

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

मुझे लगता है कि यह सबसे साफ तरीका है क्योंकि पूरा "क्लास" भी सुलभ नहीं है।


लेकिन इस तकनीक से आपके पास एक से अधिक उदाहरण हो सकते हैं। यह सही नहीं है।
निकोलस्कॉलमैन

1
मुझे ऐसा नहीं लगता, आप getInstance से गुजरे बिना कक्षा तक भी नहीं पहुँच सकते। क्या आप विस्तृत कर सकते हैं?
डेविड

डेविड मेस सॉरी लेकिन मैंने दूसरे उदाहरण में सत्यापन को नोटिस नहीं किया। मैं क्षमाप्रार्थी हूं।
निकोलस्कॉलमैन

4

@CMS और @zzzzBov दोनों ने अद्भुत जवाब दिए हैं, लेकिन सिर्फ मेरी खुद की व्याख्या को जोड़ने के लिए जो कि भारी नोड में स्थानांतरित हो गए हैं। PHP / Zend फ्रेमवर्क से विकास जहां सिंगलटन पैटर्न सामान्य थे।

निम्नलिखित, टिप्पणी-दस्तावेज कोड निम्नलिखित आवश्यकताओं पर आधारित है:

  • फंक्शन ऑब्जेक्ट का एक और केवल एक उदाहरण तुरंत हो सकता है
  • उदाहरण सार्वजनिक रूप से उपलब्ध नहीं है और केवल एक सार्वजनिक विधि के माध्यम से पहुँचा जा सकता है
  • कंस्ट्रक्टर सार्वजनिक रूप से उपलब्ध नहीं है और केवल तभी इंस्टेंट हो सकता है जब पहले से उपलब्ध कोई उदाहरण न हो
  • कंस्ट्रक्टर की घोषणा को अपनी प्रोटोटाइप श्रृंखला को संशोधित करने की अनुमति देनी चाहिए। यह निर्माणकर्ता को अन्य प्रोटोटाइप से विरासत में लेने की अनुमति देगा, और उदाहरण के लिए "सार्वजनिक" तरीके प्रदान करेगा

मेरा कोड @ zzzzBov से बहुत मिलता-जुलता है, सिवाय इसके कि मैंने कंस्ट्रक्टर में एक प्रोटोटाइप श्रृंखला को जोड़ा है और अधिक टिप्पणियाँ जो PHP या एक समान भाषा से आने वाले लोगों की मदद करें, पारंपरिक OOP को 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 द्वारा प्रदान किए गए कोड में अच्छी तरह से प्रदर्शित किया गया है। यहां एकमात्र पकड़ यह है कि कंस्ट्रक्टर की प्रोटोटाइप श्रृंखला को संशोधित करना संभव नहीं है, जब कंस्ट्रक्टर खुद गुमनाम हो।

यह ध्यान रखें कि जावास्क्रिप्ट के लिए, "सार्वजनिक" और "निजी" की अवधारणाएं लागू नहीं होती हैं जैसा कि वे PHP या जावा में करते हैं। लेकिन हमने जावास्क्रिप्ट के कार्यात्मक गुंजाइश उपलब्धता के नियमों का लाभ उठाकर एक ही प्रभाव प्राप्त किया है।


आपके कोड से कई उदाहरण बनाए जा सकते हैं:var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
zzzzBov

@zzzzBov: मैं सिर्फ अपनी
फिडेल

4

यकीन नहीं होता कि कोई भी इसे क्यों नहीं लाया है, लेकिन आप ऐसा कर सकते हैं:

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

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

यह getInstance पद्धति को छोड़ना और अधिक सरल समाधान प्राप्त करने का एक अच्छा तरीका है। लेकिन ध्यान रखें कि फ़ाइल को पार्स करने के साथ ही सिंगलटन निष्पादित हो जाएगा, जिसका अर्थ है कि डोम श्रोताओं को $ (दस्तावेज़) में पहले से ही लपेटा जाना चाहिए। पहले से ही कार्य
HoffZ

4

सबसे स्पष्ट उत्तर यह है कि 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;
    }
 
  };
 
})();


3

मेरा मानना ​​है कि यह सबसे सरल / साफ और सबसे सहज तरीका है, हालांकि इसके लिए ES7 की आवश्यकता होती है:

export default class Singleton {

  static instance;

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

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

}

स्रोत कोड से है: adam-bien.com


यह पूरी तरह से गलत है और कॉल करने पर त्रुटि होगीnew Singleton()
उत्कर्षप्रमोदगुप्ता

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

मुझे जो करने की जरूरत है वह सिर्फ इस सीएफ द्वारा बनाई गई प्रत्येक वस्तु समान होगी।

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

परीक्षा

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

2

मैंने निम्नलिखित को सबसे आसान सिंगलटन पैटर्न पाया है, क्योंकि नए ऑपरेटर का उपयोग करने से यह फंक्शन के भीतर तुरंत उपलब्ध हो जाता है, जिससे एक वस्तु शाब्दिक वापसी की आवश्यकता समाप्त हो जाती है:

var singleton = new (function () {

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

singleton.printSomething();


2

यहाँ जावास्क्रिप्ट में सिंगलटन पैटर्न को समझाने का सरल उदाहरण है।

 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;
}
  • यह काम करने के लिए आर्गेज होना चाहिए, यदि आपके पास खाली चर हैं, तो [

  • मैंने फ़ंक्शन में विंडो ऑब्जेक्ट का उपयोग किया था लेकिन मैं अपना स्वयं का दायरा बनाने के लिए एक पैरामीटर में पारित कर सकता था

  • नाम और निर्माण पैरामीटर केवल काम करने के लिए खिड़की [] के लिए स्ट्रिंग हैं लेकिन कुछ सरल प्रकार की जाँच के साथ, window.name और window.construct भी संभव है।


1

इस तरह से कैसे, बस बीमा फिर से नया नहीं हो सकता है।

इसके द्वारा, आप instanceofसेशन का उपयोग कर सकते हैं , साथ ही, आप क्लास को इनहेरिट करने के लिए प्रोटोटाइप चेन का उपयोग कर सकते हैं, यह एक रेगुलर क्लास है, लेकिन इसे नया नहीं कर सकते हैं, यदि यूयू सिर्फ उदाहरण का उपयोग करना चाहते हैं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

आप इसे इस प्रकार से डेकोरेटर के साथ कर सकते हैं, उदाहरण के लिए टाइपस्क्रिप्ट के लिए नीचे:

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

इस लेखन के रूप में, डेकोरेटर जावास्क्रिप्ट इंजन में आसानी से उपलब्ध नहीं हैं। आपको यह सुनिश्चित करने की आवश्यकता होगी कि आपके जावास्क्रिप्ट रनटाइम में सज्जाकार वास्तव में सक्षम हैं या बैबिल और टाइपस्क्रिप्ट जैसे संकलक का उपयोग करते हैं।

यह भी ध्यान दें कि सिंगलटन उदाहरण "आलसी" बनाया गया है, अर्थात, यह केवल तभी बनाया जाता है जब आप इसे पहली बार उपयोग करते हैं।


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 (); // -> मैं एक सार्वजनिक विधि चेतावनी ("हाय im एक निजी विधि") पर एक निजी विधि कह रहा हूँ

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


1

सिंगलटन:

सुनिश्चित करें कि एक वर्ग के पास केवल एक ही उदाहरण है और उसे वैश्विक पहुँच प्रदान करना है।

सिंगलटन पैटर्न किसी विशेष वस्तु के उदाहरणों की संख्या को केवल एक तक सीमित करता है। इस एकल उदाहरण को सिंगलटन कहा जाता है।

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


1

मेरे लिए सबसे सरल / साफ-सुथरा मतलब यह है कि केवल समझने के लिए कोई घंटी और सीटी नहीं है क्योंकि चर्चा के जावा संस्करण में बहुत चर्चा की जाती है:

जावा में सिंगलटन पैटर्न को लागू करने का एक प्रभावी तरीका क्या है?

जो उत्तर मेरे दृष्टिकोण से सबसे सरल / सबसे अच्छा होगा, वह है:

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

और इसे केवल आंशिक रूप से जावास्क्रिप्ट में अनुवादित किया जा सकता है। जावास्क्रिप्ट में कुछ अंतर हैं:

  • कंस्ट्रक्टर निजी नहीं हो सकते
  • कक्षाएँ घोषित क्षेत्र नहीं हो सकतीं

लेकिन नवीनतम ECMA सिंटैक्स दिए जाने से यह संभव है:

जावास्क्रिप्ट क्लास उदाहरण के रूप में सिंगलटन पैटर्न

 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.