자바스크립트 네이티브 프로토타입
조회수 532회
https://ko.javascript.info/function-prototype
이 글 ( https://ko.javascript.info/function-prototype ) 에서 함수의 prototype 프로퍼티는 [[Prototype]]과는 다르고, new를 호출할 때 만들어지는 새로운 객체의 [[Prototype]]만을 설정한다고 했었는데요. 이 글의 https://ko.javascript.info/native-prototypes 네이티브 프로토타입 변경하기
를 보고 확인해보니, String.prototype에 새로운 프로퍼티를 추가해 줄 경우에는 이미 생성된 객체의 [[Prototype]]에도 영향을 미치는 것 같습니다. 기존에 생성되어 있는 객체의 [[Prototype]]에는 영향을 주지 못하고, 새로 생성되는 String 객체의 [[Prototype]]에 대해서만 영향을 미쳐야 하는 것이 아닌가요?
제가 잘못 이해한 부분이 있을까요? 왜 이러한 결과가 나오는지 이유가 궁금합니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
2 답변
-
각 글을 따로 읽었을 때는 해당 상황에 맞는 설명만 써 있어서 문제가 없는데
이 두 글을 같이 비교하면서 읽게 되면 뭔가 혼동이 오는 것 같네요.
이 첫 번째 글은 Function을
new
키워드로 인스턴스화 했을때 만들어지는 객체가 생성자 함수와prototype
프로퍼티를 통해 어떻게 관계가 맺어지는지를 설명하고 있습니다.여기서
prototype 변경하기
라고 나오는데,function Rabbit() {} Rabbit.prototype = { jumps: true };
코드상으로 보면 기존의
prototype
에 있는 값을 다른 값 ({jumps:true}
) 으로 대체하고 있습니다.function Rabbit() {} console.log(Rabbit.prototype); // {constructor: ƒ} Rabbit.prototype = {jumps: true}; console.log(Rabbit.prototype); // {jumps: true}
이 변경을 후술할 내용과 혼동하지 않기 위해
prototype 재정의
라고 합시다.
두 번째 글입니다. 네이티브 객체를 예를 들어 prototype chain 이 어떻게 동작하는지 설명하고 있습니다.
여기서도
변경
이라는 용어를 사용하고 있습니다. 하지만 변경 방식은 좀 다른데요.String.prototype.show = function() { alert(this); };
기존의
prototype
프로퍼티에show
라는 프로퍼티(함수)를 추가 했네요. 이건prototype
에 다른 값을 재할당 한 것이 아니므로 기존String.prototype
에 존재했던 다른 프로퍼티(함수)들은 유지되고show
라는 함수만 추가된 상황입니다.function Rabbit() {} console.log(Rabbit.prototype); // {constructor: ƒ} Rabbit.prototype.jumps = true; console.log(Rabbit.prototype); // {jumps: true, constructor: ƒ}
이 변경은
prototype 확장
이라고 합시다.
prototype 재정의
와prototype 확장
은 둘 다prototype
을 변경시키는 것은 맞으나prototype 재정의
를 할 경우 기존 생성자 함수의 프로토타입 속성들을 잃어버립니다.인스턴스화 하여 생성된 객체는 생성 당시의 생성자 함수의
prototype
을 참조 하고 있습니다.하지만 생성자 함수의
prototype 재정의
이 후에 인스턴스화 하여 생성된 객체는 재정의 이후의prototype
만을 참조할 뿐 재정의 이 전의 객체는 접근할 수 없죠.이런 성질 때문에 글에서
딱 한 번만 쓸 수 있는 이용권
이라는 표현을 쓴 겁니다. (백업을 해 두지 않는다는 가정 하에...)다음의 예제를 보시면 이해에 도움이 되실 겁니다.
function Rabbit() {} Rabbit.prototype = {jumps: true}; // 첫 번째 토끼 var rabbit1 = new Rabbit(); console.log(rabbit1.jumps); // true // 생성자 함수의 prototype이 재정의 되었지만 // 이미 그 전에 만들어진 인스턴스 객체가 참조하는건 // 재정의 이 전 프로토타입 객체이므로 영향을 받지 않는다. Rabbit.prototype = {shortEars: false}; console.log(rabbit1.jumps); // true // 두 번째 토끼 // 위에서 prototype이 재정의 되었으므로 // jumps는 정의되어 있지 않다. // 대신 재정의 된 속성 값은 제대로 들어가 있다. var rabbit2 = new Rabbit(); console.log(rabbit2.jumps); // undefined console.log(rabbit2.shortEars); // false // rabbit2가 참조하는 프로토타입을 따로 저장하고 (위에 언급한 백업) // 다시 생성자 함수의 prototype을 재정의 해 보자. var temp = Rabbit.prototype; Rabbit.prototype = {redEyes: true}; // rabbit2또한 rabbit1이 그랬던 것처럼 영향을 받지 않는다. console.log(rabbit2.shortEars); // false console.log(rabbit2.redEyes); // undefined // 하지만 재정의 이전에 prototype이었던 temp를 변경하면 // rabbit2에도 반영됨을 확인할 수 있다. // 기존 속성값을 변경하거나, temp.shortEars = true; console.log(rabbit2.shortEars); // true // 새로운 속성을 추가해도 반영된다. temp.shortTail = true; console.log(rabbit2.shortTail); // true
참고로 한 객체가 참조하는 프로토타입은 그 객체의
__proto__
속성을 통해 확인할 수 있습니다.위의 예제에서 나온 값들을 가지고 비교해 보면
// 프로토타입으로 참조하는 객체가 서로 다르므로 false. rabbit1.__proto__ === rabbit2.__proto__ // false // 서로 같으므로 true. temp === rabbit2.__proto__ //true
이렇게 나오는데, 이는 생성자 함수의 프로토타입이 이미 인스턴스화 된 객체에 영향을 미칠 수 있다는 증거이기도 합니다.
이제
prototype 확장
을 예시로 살펴보고 마무리하겠습니다. 지금까지 정확하게 이해하셨다면 이건 쉬울거에요.function Rabbit() {} // 일단 처음에는 prototype 재정의 Rabbit.prototype = {jumps: true}; // 확장 이 전에 인스턴스 객체를 하나 만든다. var rabbit1 = new Rabbit(); // 생성자 함수의 prototype 속성에 존재하는 jumps가 반영되어 있다. // 지정한 적이 없는 longEars는 undefined. console.log(rabbit1.jumps, rabbit1.longEars); // true undefined // 확장 시도 Rabbit.prototype.longEars = true; // 이미 인스턴스화 한 객체에 반영 된다. console.log(rabbit1.jumps, rabbit1.longEars); // true true // 확장 시도 이 후에 만들어진 인스턴스도 마찬가지다. var rabbit2 = new Rabbit(); console.log(rabbit2.jumps, rabbit2.longEars); // true true // 두 인스턴스의 prototype은 같은 객체를 바라보고 있으며 rabbit1.__proto__ === rabbit2.__proto__ // true // 그 객체는 생성자 함수의 prototype이다. rabbit1.__proto__ === Rabbit.prototype // true
- https://poiemaweb.com/js-prototype 요기에 더 잘 나와 있습니다. doodoji 2020.4.9 14:07
- 원 따봉 드립니다. 👍 편집요청빌런 2020.4.9 16:36
- 확인이 늦었네요... 명쾌한 답변 감사드립니다!! 알 수 없는 사용자 2020.4.11 12:36
-
프로토타입의 동작 방식은 '신비스러운’면이 있습니다. object에서 프로퍼티를 읽으려고 하는데 해당 프로퍼티가 없으면 자바스크립트는 자동으로 프로토타입에서 프로퍼티를 찾기 때문이죠. 프로그래밍에선 이런 동작 방식을 '프로토타입 상속’이라 부릅니다.
라네요.
전에 만들어진 객체나, 새로 만들어진 객체나 같은 생성자 함수로 만든거면 프로토타입도 같을거고 그 다음은 위의 설명처럼 되겠죠?
댓글 입력