2020. 3. 2. 15:13ㆍ웹/Javascript Pattern
설명
-
싱글톤 패턴은 특정 클래스의 인스턴스를 오직 하나만 유지
-
동일한 클래스를 사용하여 새로운 객체를 생성하면, 두번째 부터는 처음 만들어진 객체를 얻게 된다.
자바스크립트에서 싱글톤 패턴
-
자바스크립트에는 클래스가 없고 오직 객체만 있다.
-
새로우 객체를 만들면 실제로는 이 객체는 다른 어떤 객체와도 같지 않기 때문에 이미 싱글톤이다.
var obj = {
myprop : 'my value'
}
var obj2 = {
myprop : 'my value'
}
obj === obj2; // false
obj == obj2; // false
new 연산자를 사용한 싱글톤 패턴 구현
var uni = new Universe();
var uni2 = new Universe();
uni === uni2; // true
설명
-
uni는 생성자가 처음 호출되었을 때만 생성, 이후 호출(uni2) 부터는 동일한 uni 객체가 반환된다.
-
변수들은 동일한 객체를 가리키는 참조일 뿐.
-
객체의 인스턴스인 this가 생성되면 Universe 생성자가 이를 캐시한 후, 그 다음번에 생성자가 호출되었을 때 캐시된 인스턴스를 반환
위와 같은 결과를 얻기 위한 고려할 점
1. 인스턴스를 저장하기 위해 전역 변수 선언?
=> 일반적인 원칙상 전역 변수 선언은 좋지 않다. 누군가가 전역 변수를 덮어 쓸수있기 때문
2. 생성자 스태틱 프로퍼티에 인스턴스 저장?
=> Universe.instance와 같은 프로퍼티에 인스턴스를 저장할 수 있다.
하지만 instance 프로퍼티가 공개되기 때문에 외부 코드에서 값을 변경하면 인스턴스를 잃어버릴 수 있다는 단점
3. 인스턴스 클로저로 감싸는 방법?
=> 인스턴스를 비공개로 만들어 생성자 외부에서 수정할 수 없게 해준다. 추가적인 클로저가 필요한 단점
클로저에 인스턴스 저장
function Universe() {
// 캐시된 인스턴스
var instance= this;
this.start_time = 0;
this.bang = "Big";
// 생성자 생성
Universe = function() {
return instance;
};
}
// TEST
var uni = new Universe();
var uni2 = new Universe();
uni === uni2; // true
설명
-
원본 생성자가 최초 호출 시 this를 반환
-
두번째 호출 이상 부터 재작성된 생성자 실행
-
재작성된 생성자를 통해 비공개 instance 변수에 접근하여 instnace 반환
단점
-
재작성된 함수는 재정의 시점 이전에 원본 생성자에 추가된 프로퍼티를 잃어버리는 점
-
Universe()의 프로토타입에 무언가를 추가해도 원본생성자로 생성된 인스턴스와 연결되지 않는다
// 프로토타입에 추가
Universe.prototype.nothing = true;
var uni = new Universe();
// 첫번째 객체 생성 이후, 다시 프로토타입에 추가
Universe.prototype.everything = true;
// 두번째 객체 생성
var uni2 = new Universe();
// TEST
uni.nothing; // true
uni2.nothing; // true
uni.everything; // undefined
uni2.everything; // undefined
uni.constructor.name; // Universe
uni.constructor === Universe; // false
설명
-
uni.contructor가 더이상 Universe() 생성자와 같지 않는 이유는 uni.constructor가 재정의된 생성자가 아닌 원본생성자를 가리키고 있기 때문.
프로토타입/생성자 포인터 정상 동작 방안 1
function Universe() {
// 캐시된 인스턴스
var instance;
// 생성자 재작성
Universe = function() {
return instance;
};
// prototype 프로퍼티 변경
Universe.prototype = this;
// instnace
instance = new Universe();
// 생성자 포인트 재지정
instance.constructor = Universe;
instance.start_time = 0;
instance.bang = "Big";
return instance;
}
// TEST
// 프로토타입에 추가
Universe.prototype.nothing = true;
var uni = new Universe();
// 첫번째 객체 생성 이후, 다시 프로토타입에 추가
Universe.prototype.everything = true;
// 두번째 객체 생성
var uni2 = new Universe();
uni === uni2; // true
uni.nothing; // true
uni2.nothing; // true
uni.everything; // true
uni2.everything; // true
uni.constructor.name; // Universe
uni.constructor === Universe; // true
프로토타입/생성자 포인터 정상 동작 방안 2
var Universe;
(function() {
var instance;
Universe = function Universe() {
if (instance) {
return instance;
}
instance = this;
this.start_time = 0;
this.bang = "Big";
}
}());
설명
-
생성자와 인스턴스를 즉시 실행함수로 감싼다.
-
생성자가 최초호출 되면, 생성자는 객체를 생성하고 비공개 instance를 가리킨다
-
두번째 호출부터는 단순히 비공개 변수를 반환
출처 : JavaScript Patterns
'웹 > Javascript Pattern' 카테고리의 다른 글
코드 재사용 패턴(새로운 방식의 상속) - 프로퍼티 복사를 통한 상속 패턴 (0) | 2020.03.02 |
---|---|
코드 재사용 패턴(새로운 방식의 상속) - 프로토타입을 활용한 상속 (0) | 2020.03.02 |
코드 재사용 패턴(클래스 방식의 상속) - 프로토타입 공유 (0) | 2020.03.02 |
코드 재사용 패턴(클래스 방식의 상속) - 생성자 빌려쓰기 (0) | 2020.03.02 |
코드 재사용 패턴(클래스 방식의 상속) - 기본패턴 (0) | 2020.03.02 |