Programing

JavaScript에서 싱글 톤을 구현하는 가장 간단하고 깔끔한 방법은 무엇입니까?

lottogame 2020. 3. 21. 10:09
반응형

JavaScript에서 싱글 톤을 구현하는 가장 간단하고 깔끔한 방법은 무엇입니까?


JavaScript에서 싱글 톤 패턴을 구현하는 가장 간단하고 깨끗한 방법은 무엇입니까?


가장 쉬운 방법은 간단한 객체 리터럴을 선언하는 것입니다.

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

싱글 톤 인스턴스에 비공개 멤버를 원하면 다음과 같이 할 수 있습니다.

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

  function privateMethod () {
    // ...
  }

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

이를 모듈 패턴 이라고 하며 , 기본적으로 클로저를 사용하여 객체에 개인 멤버를 캡슐화 할 수 있습니다 .

업데이트 : 싱글 톤 객체의 수정을 방지 하려면 ES5 방법을 사용하여 고정 할 수 있다고 덧붙이고 싶습니다 Object.freeze.

그러면 객체가 변경되지 않고 구조와 값이 수정되지 않습니다.

또한 ES6을 사용하는 경우 ES 모듈을 사용하여 싱글 톤을 매우 쉽게 나타낼 수 있으며 모듈 범위 에서 변수를 선언하여 개인 상태유지할 수도 있습니다 .

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

function privateFn () {
  // ...
}

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

그런 다음 싱글 톤 객체를 가져 와서 사용할 수 있습니다.

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

가장 깨끗한 접근 방식은 다음과 같습니다.

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

이후에 함수를 다음과 같이 호출 할 수 있습니다.

var test = SingletonFactory.getInstance();

싱글 톤 패턴의 대체물로 사용되는 모듈 패턴에 동의하지 않습니다. 필자는 싱글 톤이 완전히 불필요한 곳에서 사용되고 남용되는 것을 자주 보았으며, 프로그래머가 싱글 톤을 사용하는 경우 모듈 패턴이 많은 간격을 채우지 만 모듈 패턴은 싱글 톤 아니라고 확신합니다 .

모듈 패턴 :

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

고양이를 피부에 바르는 방법은 여러 가지가 있습니다 :) 당신의 취향이나 특정한 필요에 따라 제안 된 솔루션을 적용 할 수 있습니다. 가능하면 개인 정보 보호가 필요하지 않은 경우 CMS의 첫 번째 솔루션을 개인적으로 선택합니다. 질문이 가장 단순하고 깨끗하다는 것이 었으므로 이것이 승자입니다. 또는:

var myInstance = {}; // done!

이것은 (내 블로그에서 인용) ...

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

개인 var가 필요 없기 때문에 이해가되지 않습니다 (내 블로그 예제도 마찬가지입니다). 그래서 다음과 거의 같습니다.

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의 비 차단 특성으로 인해 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();
});

설명:

싱글 톤은 전체 애플리케이션을 통해 하나 이상의 인스턴스를 제공합니다. 초기화는 처음 사용할 때까지 지연됩니다. 초기화가 비싼 객체를 다룰 때 이것은 정말 큰 일입니다. 비용이 많이 드는 것은 일반적으로 I / O를 의미하며 JavaScript의 경우 I / O는 항상 콜백을 의미합니다.

와 같은 인터페이스를 제공하는 답변을 신뢰하지 마십시오 instance = singleton.getInstance(). 모두 요점을 놓칩니다.

인스턴스가 준비 될 때 콜백을 실행하지 않으면 초기화 프로그램이 I / O를 수행 할 때 작동하지 않습니다.

예, 콜백은 항상 객체 인스턴스를 즉시 반환하는 함수 호출보다 더 나빠 보입니다. 그러나 다시 : I / O를 수행 할 때 콜백은 필수입니다. I / O를 원하지 않는 경우 인스턴스화는 프로그램 시작시 수행하기에 충분히 저렴합니다.

예 1, 저렴한 이니셜 라이저 :

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

var simple = singleton(simpleInitializer);

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

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

예제 2, I / O로 초기화 :

이 예 setTimeout에서는 값 비싼 I / O 작업을 위조합니다. 이것은 JavaScript의 싱글 톤에 실제로 콜백이 필요한 이유를 보여줍니다.

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

var heavy = singleton(heavyInitializer);

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

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

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

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

JavaScript 패턴 에서이 예제를 얻었습니다. 코딩 및 디자인 패턴으로 더 나은 응용 프로그램 빌드 Stoyan Stefanov 의 저서 singltone 객체와 같은 간단한 구현 클래스가 필요한 경우 다음과 같이 즉각적인 기능을 사용할 수 있습니다.

var ClassName;

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

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

다음 테스트 사례를 통해이 예제를 확인할 수 있습니다.

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

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

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


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

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

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

이 접근법은 프로토 타입 확장을 사용할 때 (고정 될 수는 있지만 단순하지는 않지만) 개인 정적 구현이 실패하고 인스턴스로 인해 공개 정적 구현이 권장되지 않는 경우 모든 테스트 사례를 통과합니다.

jsFiddly 데모.


JavaScript로 프로그래밍하는 가장 깨끗한 방법을 찾았지만 상상력이 필요합니다. 나는 "javascript the good parts"라는 책의 작동 기술에서이 아이디어를 얻었다.

새 키워드를 사용하는 대신 다음과 같은 클래스를 만들 수 있습니다.

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

    var privateVar;
    obj.publicVar;

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

    function privateMethod(){} 

    return obj;
}

다음과 같이 말하면 위의 객체를 인스턴스화 할 수 있습니다.

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

이제이 작업 방법을 염두에두고 다음과 같이 싱글 톤을 만들 수 있습니다.

ClassSingleton = function()
{
    var instance= null;

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

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

        return instance;
    }   

    return { getInstance : getInstance };

}();

이제 전화를 걸어 인스턴스를 얻을 수 있습니다

var obj = ClassSingleton.getInstance();

완전한 "클래스"에 액세스 할 수 없기 때문에 이것이 가장 쉬운 방법이라고 생각합니다.


다음은 노드 v6에서 작동합니다.

class Foo {
  constructor(msg) {

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

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

우리는 테스트 :

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

@CMS와 @zzzzBov는 훌륭한 답변을 주었지만 싱글 톤 패턴이 일반적인 PHP / Zend Framework에서 무거운 node.js 개발로 옮겨 간 것에 근거하여 내 자신의 해석을 추가하기 만하면됩니다.

다음 주석으로 작성된 코드는 다음 요구 사항을 기반으로합니다.

  • 함수 객체의 하나의 인스턴스 만이 인스턴스화 될 수있다
  • 인스턴스는 공개적으로 사용할 수 없으며 공개 메소드를 통해서만 액세스 할 수 있습니다
  • 생성자는 공개적으로 사용할 수 없으며 사용 가능한 인스턴스가없는 경우에만 인스턴스화 할 수 있습니다
  • 생성자의 선언은 프로토 타입 체인을 수정해야합니다. 이를 통해 생성자는 다른 프로토 타입에서 상속하고 인스턴스에 대한 "공개"메소드를 제공 할 수 있습니다.

내 코드는 @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에서 제공 한 코드에서 잘 설명 된대로 자체적으로 싱글 톤입니다. 여기서 유일한 발견은 생성자 자체가 익명 인 경우 생성자의 프로토 타입 체인을 수정할 수 없다는 것입니다.

Javascript의 경우 "public"및 "private"개념은 PHP 또는 Java에서와 같이 적용되지 않습니다. 그러나 Javascript의 기능 범위 가용성 규칙을 활용하여 동일한 효과를 얻었습니다.


아무도 이것을 제기하지 않은 이유는 확실하지 않지만 다음과 같이 할 수 있습니다.

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

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

가장 분명한 답은 Addy Osmani의 Learning JavaScript Design Patterns 책에서 나온 것입니다.

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


이게 뭐가 문제 야?

function Klass() {
   var instance = this;
   Klass = function () { 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)

ES7이 필요하지만 가장 간단하고 깨끗하며 직관적 인 방법이라고 생각합니다.

export default class Singleton {

  static instance;

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

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

}

소스 코드는 다음과 같습니다 : adam-bien.com


new 연산자를 사용 하면 함수 내에서 이것을 즉시 사용할 수 있으므로 객체 리터럴을 반환 할 필요가 없기 때문에 다음이 가장 쉬운 Singleton 패턴이라는 것을 알았습니다 .

var singleton = new (function () {

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

singleton.printSomething();


다음은 자바 스크립트에서 싱글 톤 패턴을 설명하는 간단한 예입니다.

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

나는 몇 가지 싱글 톤이 필요했습니다.

  • 게으른 초기화
  • 초기 매개 변수

그래서 이것은 내가 생각해 낸 것입니다.

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;
}
  • 빈 변수가 있으면 [] 만 전달하면됩니다.

  • 함수에서 창 객체를 사용했지만 매개 변수를 전달하여 자체 범위를 만들 수있었습니다.

  • name 및 construct 매개 변수는 window []가 작동하기위한 문자열 일 뿐이며 간단한 유형 검사를 통해 window.name 및 window.construct도 가능합니다.


이런 식으로 수업을 다시 시작할 수 없도록하십시오.

이를 통해 instanceofop를 사용할 수 있으며 프로토 타입 체인을 사용하여 클래스를 상속 할 수 있습니다. 일반 클래스이지만 인스턴스를 사용하려면 새 클래스를 사용할 수 없습니다getInstance

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

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

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

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

instance멤버 를 노출시키지 않으려면 멤버를 클로저에 넣으십시오.


다음은 싱글 톤 패턴을 구현하기 위해 걷는 스 니펫입니다. 이것은 인터뷰 과정에서 나에게 일어 났고 나는 이것을 어딘가에 포착해야한다고 느꼈다.

/*************************************************
   *     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와 같은 컴파일러를 사용해야합니다.

또한 싱글 톤 인스턴스는 "lazy"로 작성됩니다. 즉, 처음 사용할 때만 작성됩니다.


모듈 패턴 : "더 읽기 쉬운 스타일" 어떤 방법이 공개인지, 어떤 방법이 비공개인지 쉽게 볼 수 있습니다

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 (); //-> 공개 메소드 알림 ( "hi im a private method")을 통해 비공개 메소드를 호출하고 있습니다.

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


하나씩 일어나는 것:

클래스에 인스턴스가 하나만 있는지 확인하고 글로벌 액세스 지점을 제공하십시오.

싱글 톤 패턴은 특정 객체의 인스턴스 수를 하나로 제한합니다. 이 단일 인스턴스를 싱글 톤이라고합니다.

  • 고유 인스턴스를 리턴하는 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()


나는 단일 패턴과 모듈 패턴, Global 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)}`);

circle.js의 내용 :

const PI = Math.PI;

exports.area = (r) => PI * r * r;

exports.circumference = (r) => 2 * PI * r;

circle.PI내보내기 되지 않은에 액세스 할 수 없습니다 .

브라우저에서는 작동하지 않지만 간단하고 깨끗합니다.


주요 열쇠는 Undertand Closure의 중요성입니다. 따라서 내부 함수 내부의 속성은 클로저를 통해 비공개입니다.

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

};

};


모든 new실행 에서 동일한 인스턴스를 반환 할 수 있습니다.

function Singleton() {
    // lazy 
    if (Singleton.prototype.myInstance == undefined) {
        Singleton.prototype.myInstance = { description: "I am the instance"};
    }
    return Singleton.prototype.myInstance;
}

a = new Singleton();
b = new Singleton();
console.log(a); // { description: "I am the instance"};
console.log(b); // { description: "I am the instance"};
console.log(a==b); // true

참고 URL : https://stackoverflow.com/questions/1479319/simplest-cleanest-way-to-implement-singleton-in-javascript

반응형