[JS] 문법정리 > 확실한 프로토타입 체이닝 정리
[JS] 문법정리 > 확실한 프로토타입 체이닝 정리
'자바스크립트'는 기존 C++ 이나 자바 같은 객체지향 프로그래밍 언어와는 다른
프로토타입 기반의 객체지향 프로그래밍을 지원한다.
즉, 프로토타입(prototype) 에 대해 잘 이해하고 있어야, 자바스크립트의 동작 과정을 제대로 이해할 수 있다.
이번 포스팅의 결론이자 규칙을 먼저 기억하자.
📌규칙
JS에서 "모든 객체" 는
자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를
자신의 프로토타입 객체(부모 객체)로 취급한다.
예제
function Factory(name) {
this.name = name;
}
// box 객체 생성
var box = new Factory('box');
console.dir(Factory);
console.log(box);
예제 코드의 관계도를 그림으로 표현해보면 다음과 같다.
앞서 살펴본 규칙대로, 자바스크립트의 모든 객체는
자신의 부모의 프로토타입 객체를 가리키는 참조 링크 형태의 숨겨진 프로퍼티가 있다.
이 링크를 암묵적 프로토타입 링크(implicit prototype link) 라고 부르고,
자신의 [[prototype]] 프로퍼티에 저장한다.
이 예제에 적용해보면
"생성자 함수 Factory 의 prototype 프로퍼티" 와 "자식인 box 객체의 [[prototype]] 프로퍼티" 가 같은 객체를 가리킨다.
즉, 자바스크립트에서 객체를 생성하는 건 생성자 함수의 역할이지만,
생성된 객체의 실제 부모 역할을 하는 건
생성자 자신이 아닌 생성자의 prototype 프로퍼티가 가리키는 프로토타입 객체이다
📌참고
이 숨겨진 링크는 ECMAScript에서는 [[prototype]] 프로퍼티로 정하고 내부적으로만 사용된다고 명시하고 있다.
하지만 크롬, 파이어폭스에서는 __proto__ 프로퍼티로 명시적으로 제공하고 있다.
즉, __proto__ 프로퍼티 와 [[prototype]] 프로퍼티는 같다고 간주하면 된다.
→ __proto__=== [[prototype]] // true
1. 객체 리터럴 방식에서의 프로토타입 체이닝
자바스크립트에서는 객체에 접근하려는 프로퍼티가 없을 경우,
자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티에도 접근이 가능하다.
이것이 프로토타입 체이닝 개념이다.
var obj = {
name: 'child',
sayName: function() {
console.log('name : ' + this.name);
}
};
obj.sayName(); // 'child'
obj.sayAge(); // Uncaught TypeError
console.log(obj.hasOwnProperty('name')); // true
console.log(obj.hasOwnProperty('age')); // false
리터럴 방식으로 obj 객체에는 sayAge 라는 프로퍼티를 가지고 있지 않다.
그렇기 때문에 "Uncaught TypeError" 에러가 발생한다.
이와 마찬가지로 hasOwnProperty 라는 프로퍼티도 가지고 있지 않다.
그런데 에러가 발생하지 않았다. 어떻게 된 일인가?!
이를 이해하려면
객체 리터럴 방식으로 객체를 생성할 때 동작 원리와 프로토타입 체이닝
이 두가지 개념을 살펴보아야 한다.
1. 객체 리터럴 방식의 동작 과정
a. 객체 리터럴 방식으로 생성한 객체는 사실 Object() 라는 내장 생성자 함수로 생성 된다.
b. Object() 생성자 함수도 함수 객체이므로, prototype 이라는 프로퍼티 속성이 있다.
따라서, 이전 예제처럼 아래와 같이 도식도를 그릴수 있다.
"객체 리터럴 방식"으로 생성한 obj 객체는
Object 함수의 prototype 프로퍼티가 가리키는 Object.prototype 객체를
자신의 [[proto]] 프로퍼티 로 연결(히든 링크!!) 한다.
2. 프로토타입 체이닝
obj.hasOwnProperty 와 같이
객체에 없는 프로퍼티에 접근하려고 할 때
히든링크인 [[prototype]] 링크를 따라
자신의 부모 역할을 하는 프로토타입 객체(Object.prototype)에서
프로퍼티를 차례대로 검색하는 것을 "프로토타입 체이닝" 이라고 한다.
위의 예제에서는 obj.hasOwnProperty 를 obj 에서 찾는데 실패하였기 때문에,
프로토타입 체이닝이 발생하여, 히든링크를 타고 올라가 프로토타입 객체에서 해당 프로퍼티를 발견했다.
📌참고
Object.prototype 객체는 자바스크립트 모든 객체의 조상 역할을 하는 객체로,
toString(), hasOwnProperty() 등과 같은 표준 메서드를 제공한다.
이는 ECMAScript 에 명세되어있다.
2. 생성자 함수로 생성된 객체의 프로토타입 체이닝
"생성자 함수로 생성된 객체"는
앞서 살펴본 객체 리터럴 방식으로 생성된 객체와 약간 다른 프로토타입 체이닝이 이루어진다.
하지만, 기본 규칙은 변하지 않는다.
📌규칙
JS에서 모든 객체는
자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를
자신의 프로토타입 객체(부모 객체)로 취급한다.
예제를 통해 살펴보자.
// Factory() 생성자 함수
function Factory(name, number) {
this.name = name;
this.number = number;
}
// box 객체 생성
var box = new Factory('box', 30);
// 프로토타입 체이닝
console.log(box.hasOwnProperty('name'));
// Factory.prototype 객체 출력
console.dir(Factory.prototype);
앞서 살펴본 것처럼, box 객체의 [[prototype]] 객체는
Factory 생성자 함수 객체의 prototype 프로퍼티가 가리키는 객체(Factory.prototype) 과 동일하다.
여기서 프로토타입 체이닝 일어나는 단계는 다음과 같다.
1. box.hasOwnProperty() 메서드를 호출했지만, box 객체 에는 해당 프로퍼티가 없었다.
2. 첫 번째 프로토타입 체이닝이 발생
Factory.prototype 객체에서 hasOwnProperty() 메서드를 찾는다.
그러나 constructor 프로퍼티만 가질 뿐 해당 프로퍼티가 없다.
Factory.prototype 프로퍼티 역시 객체이므로 [[prototype]] 라는 히든 링크를 가지고 있다.
3. 두번째 프로토타입 체이닝 발생
모든 객체는 Object.prototype 을 프로토타입 객체로 가진다.
이 객체에서 hasOwnProperty() 메서드를 찾아서 참조하게 된다.
'프로그래밍 > JAVASCRIPT 사전' 카테고리의 다른 글
[JS] 화살표 함수, 쉽고 빠르게 정리하기 (8) | 2021.05.11 |
---|---|
[YOU DON'T KNOW JS 정리] THIS (1) (4) | 2021.05.08 |
[JS] arguments 객체 그리고 유사배열 객체 (0) | 2021.05.05 |
[JS] 문법 정리 > 함수: 선언, 호이스팅, 일급 객체 (0) | 2020.12.20 |
[JS] 문법정리 > 타입과 변수 (0) | 2020.12.09 |
댓글
이 글 공유하기
다른 글
-
[YOU DON'T KNOW JS 정리] THIS (1)
[YOU DON'T KNOW JS 정리] THIS (1)
2021.05.08 -
[JS] arguments 객체 그리고 유사배열 객체
[JS] arguments 객체 그리고 유사배열 객체
2021.05.05 -
[JS] 문법 정리 > 함수: 선언, 호이스팅, 일급 객체
[JS] 문법 정리 > 함수: 선언, 호이스팅, 일급 객체
2020.12.20 -
[JS] 문법정리 > 타입과 변수
[JS] 문법정리 > 타입과 변수
2020.12.09