一.프로토타입 패턴
기존 객체를 프로토타입으로 하여, clone 을 통해 새로운 객체를 획득합니다 (새로운 객체의 생성 프로세스를 간소화하기 위해)
([黯羽輕揚:디자인 패턴 정리 (《Head First 디자인 패턴》학습 정리)](/articles/디자인 패턴 정리 (《head-first 디자인 패턴》학습 정리)/) 에서 인용)
상속과 매우 비슷하며, 프로토타입 패턴을 더욱 강화하면 상속이 됩니다. 프로토타입 패턴은 속성 복사만 신경 쓰고, 상속은 속성 복사를 구현하는 외에 부/자 타입의 계층 관계를 보증해야 합니다
二.구체적 구현
###1.기본 원리
// 生孩子函数
function beget(obj) {
var F = function() {};
F.prototype = obj;
return new F();
}
// test
var obj = {
attr: 1,
fun: function() {
console.log(this.attr);
}
}
var cp_obj = beget(obj);
cp_obj.fun(); // 1
핵심은 beget 함수로, 전달된 객체를 빈 생성자의 프로토타입에 넣고, 객체를 생성하여 반환할 뿐입니다
명확한 단점이 있습니다: 프로토타입 객체 (이 예에서 obj) 로부터의 속성이 실수로 덮어씌워질 수 있습니다
P.S.프로토타입 객체 obj 는 어떤 방식으로 생성된 객체라도 좋으며, 이 예에서는 객체 리터럴이지만, 물론 new 로 생성된 것이라도, beget 으로 생성된 것이라도構いません
###2.간단한 강화
ES5 는 Object.create 함수를 서포트하여, 얕은 복사본의 객체를 획득할 수 있습니다. beget 을 직접 이하로 치환할 수 있습니다:
Object.create(obj);
결과는 완전히 같습니다. Object.create 의 내부 구현은 더글라스의 프로토타입 패턴에서 영감을 받았기 때문입니다. 게다가 Object.create 에는 두 번째 파라미터가 있어, 속성을 정의하는 데 사용할 수 있습니다:
Object.create(obj, {
attr: {
value: 2,
writable: false, // 디폴트 값
configurable: false, // 디폴트 값
enumerable: true
}
});
실제로는 Object.create 와 Object.defineProperty 를 함께 한 것으로, 예를 들어:
// test
var obj = {
attr: 1,
fun: function() {
console.log(this.attr);
}
}
var cp_obj = Object.create(obj, {
attr2: {
value: 2,
writable: false, // 디폴트 값
configurable: false, // 디폴트 값
enumerable: true
}
});
cp_obj.fun(); // 1
console.log(cp_obj.attr2); // 2
cp_obj.attr2 = 3;
console.log(cp_obj.attr2); // 2, 쓰기 불가
물론, Object.defineProperty 도 ES5 에서 서포트되므로, 배합하여 사용하는 것은 일종의 강화 (액세스 제어) 라고 할 수 있습니다
三.프로토타입 패턴의 이점
책에 훌륭한 말이 있습니다:
Prototype 패턴을 사용하는 이점 중 하나는, JavaScript 자체가 가진 프로토타입의 우위성을 획득할 수 있다는 것이며, 다른 언어의 특성을 모방하려는 것이 아닙니다.
Java 로 구현된 프로토타입 패턴은 이상하게 보입니다. 프로토타입 패턴 자체而言, Java 중의 Object.clone 으로 수요를 만족시킬 수 있기 때문입니다. 다른 어떠한 형태의 구현도 여분으로 보입니다. 한편, JavaScript 는 당초 clone 의 네이티브 구현을 제공하지 않았습니다 (ES5 의 Object.create 가 이 결함을 보충했습니다). 그래서 프로토타입 패턴이 필요했지만, ES5 가 생산에 투입된 후에는 수동으로 프로토타입 패턴을 구현할 필요는 없어졌습니다
프로토타입 패턴에 관한 더욱 많은 소개는 23 종 디자인 패턴 (5): 프로토타입 패턴 참조
참고 자료
-
《JavaScript 디자인 패턴》
아직 댓글이 없습니다