[JS 디자인 모드]: 단일 모드 (1)
단일 모드 소개
이른바 단례란 하나의 유형에 하나의 실례만 있는 것이다. 실현하는 방법은 일반적으로 실례가 존재하는지 여부를 먼저 판단하고 존재하면 바로 되돌아오고 존재하지 않으면 만들고 다시 되돌아오는 것이다.이렇게 하면 하나의 클래스가 하나의 실례 대상만 확보할 수 있다.
실현된 단례는 여러 가지 방식이 있는데 가장 간단한 방식은 대상의 글씨체를 재는 방법이다. 그 글씨체에는 대량의 속성과 방법이 포함될 수 있다.
var mySingleton = {
property1: "something",
property2: "something else",
method1: function () {
console.log('hello world');
}
};
이 대상을 확장하려면 패키지를 닫는 방식으로 내부에 개인 속성과 방법을 만들려면 리턴이 노출하고 싶은 공유 속성과 방법을 노출시키면 됩니다. 코드는 다음과 같습니다.
var mySingleton = function () {
/* */
var privateVariable = 'something private';
function showPrivate() {
console.log(privateVariable);
}
/* ( ) */
return {
publicMethod: function () {
showPrivate();
},
publicVar: 'the public can see this!'
};
};
var single = mySingleton();
single.publicMethod(); // 'something private'
console.log(single.publicVar); // 'the public can see this!'
자원을 절약하기 위해서 어떻게 사용할 때 초기화합니까?이 코드는 다음과 같이 다른 구조 함수에서 초기화할 수 있습니다.
var Singleton = (function () {
var instantiated;
function init() {
/* */
return {
publicMethod: function () {
console.log('hello world');
},
publicProperty: 'test'
};
}
return {
getInstance: function () {
if (!instantiated) {
instantiated = init();
}
return instantiated;
}
};
})();
/* :*/
Singleton.getInstance().publicMethod();
단례가 어떻게 실현되었는지 알았지만, 단례는 어떤 장면에 쓰면 좋을까요?사실 하나의 예는 일반적으로 시스템 간의 각종 모델의 통신 조율에 사용되는데 아래의 코드는 하나의 예에 대한 가장 좋은 실천이다.
var SingletonTester = (function () {
// :
function Singleton(args) {
// args ( )
var args = args || {};
// name
this.name = 'SingletonTester';
// pointX
this.pointX = args.pointX || 6; // ,
// pointY
this.pointY = args.pointY || 10;
}
//
var instance;
var _static = {
name: 'SingletonTester',
//
// Singleton
getInstance: function (args) {
if (instance === undefined) {
instance = new Singleton(args);
}
return instance;
}
};
return _static;
})();
var singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // 5
기타 실현 방식
방법1
function Universe() {
//
if (typeof Universe.instance === 'object') {
return Universe.instance;
}
//
this.start_time = 0;
this.bang = "Big";
//
Universe.instance = this;
// this
}
//
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
방법2
function Universe() {
//
var instance = this;
//
this.start_time = 0;
this.bang = "Big";
//
Universe = function () {
return instance;
};
}
//
var uni = new Universe();
var uni2 = new Universe();
uni.bang = "123";
console.log(uni === uni2); // true
console.log(uni2.bang); // 123
방법3
function Universe() {
//
var instance;
//
Universe = function Universe() {
return instance;
};
//
Universe.prototype = this;
//
instance = new Universe();
//
instance.constructor = Universe;
//
instance.start_time = 0;
instance.bang = "Big";
return instance;
}
//
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
//
Universe.prototype.nothing = true;
var uni = new Universe();
Universe.prototype.everything = true;
var uni2 = new Universe();
console.log(uni.nothing); // true
console.log(uni2.nothing); // true
console.log(uni.everything); // true
console.log(uni2.everything); // true
console.log(uni.constructor === Universe); // true
방식
var Universe;
(function () {
var instance;
Universe = function Universe() {
if (instance) {
return instance;
}
instance = this;
//
this.start_time = 0;
this.bang = "Big";
};
} ());
//
var a = new Universe();
var b = new Universe();
console.log(a === b); // true
a.bang = "123";
console.log(b.bang); // 123
인스턴스
예를 들어 이런 흔히 볼 수 있는 요구가 있는데 어떤 단추를 눌렀을 때 페이지에 커버층을 팝업해야 한다.
코드는 다음과 같습니다.
var createMask = function(){
return document.body.appendChild( document.createElement(div) );
}
$( 'button' ).click( function(){
Var mask = createMask();
mask.show();
})
문제는 이 마스크 층이 전역적으로 유일한 것이기 때문에createMask를 호출할 때마다 새div를 만들 수 있습니다. 마스크 층을 숨기고remove할 수 있지만.그러나 분명히 이렇게 하는 것은 불합리하다.
두 번째 방안을 보십시오. 페이지의 처음부터 이div를 만들고 변수로 인용하십시오.
var mask = document.body.appendChild( document.createElement( ''div' ) );
$( ''button' ).click( function(){
mask.show();
} )
이렇게 하면 페이지에 하나의 커버층div만 만들 수 있지만 다른 문제가 뒤따른다. 아마도 우리는 이 커버층을 영원히 필요로 하지 않을 것이다. 그러면 또한div를 낭비하고dom 노드의 어떠한 조작도 매우 인색해야 한다.
변수 하나를 빌릴 수 있다면.div가 만들어졌는지 아닌지를 판단해 볼까요?
var mask;
var createMask = function(){
if ( mask ) return mask;
else{
mask = document,body.appendChild( document.createElement(div) );
return mask;
}
}
보기에 괜찮은데, 여기에서 확실히 단열 대상을 만드는 함수를 완성했다.우리는 이 코드가 무엇이 타당하지 않은지 다시 자세히 보았다.
우선 이 함수는 일정한 부작용이 존재한다. 함수 체내에 외부 변수 mask의 인용이 바뀌었고 여러 사람이 협업하는 프로젝트에서createMask는 안전하지 않은 함수이다.다른 한편,mask라는 전역 변수는 필요하지 않으면 안 되는 것이 아니다.다시 한 번 개선해 봅시다.
var createMask = function(){
var mask;
return function(){
return mask || ( mask = document.body.appendChild( document.createElement('div') ) )
}
}()
앞의 그 단례는 여전히 결점이 있다.마스크 레이어를 생성하는 데만 사용할 수 있습니다.만약 내가 유일한 xhr 대상을 만드는 데 사용할 함수를 또 써야 한다면?통용되는singleton 포장기를 찾을 수 있습니까?
js에서 함수는 제1형으로 함수도 매개 변수로 전달할 수 있음을 의미한다.최종 코드를 보세요.
var singleton = function( fn ){
var result;
return function(){
return result || ( result = fn .apply( this, arguments ) );
}
}
var createMask = singleton( function(){
return document.body.appendChild( document.createElement('div') );
})
첫 번째 되돌림 값을 변수로 저장합니다. 만약 변수가 이미 부여되었다면, 다음 호출에서 이 변수를 우선적으로 되돌려줍니다.진정으로 커버층을 만드는 코드는 리셋 함수를 통해singleton 패키지에 전송됩니다.이런 방식을 사실 브리지 모드라고 부른다.
그러나singleton 함수도 완벽하지 않습니다.div의 인용을 저장하기 위해 변수result가 필요합니다.유감스럽게도 js의 함수식 특성은 성명과 문장을 완전히 제거하기에는 부족하다.
참고 자료
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.