Javascript/core

prototype chaining에 관하여

student513 2020. 12. 20. 21:40

참조: prototype, __proto__에 관하여

Object로부터 상속받는 생성자함수의 prototype

prototype은 객체형태이기 때문에 Object라는 생성자로부터 상속을 받는다. 

이 경우 Object의 prototype 입장에서  Array의 prototype은 __proto__으로 취급되는 것이다.

Array의 prototype이란 객체는 Object로부터 상속받은 것이다.

각 변수는 생성자 함수가 존재하며, 각 데이터타입에 해당하는 메소드가 정의되어있어,

메소드를 사용하려 할 때 해당 변수는 자동으로 instance로 변환된다.

Array 뿐만 아니라 Number, String, Boolean 등에 대해서도 동일하게 적용된다.


Object 생성자 함수는 누구로부터 상속을 받을까?

그렇다면 다른 생성자들의 부모격인 Object의 prototype은 어떤 상속구조를 가질까?

객체 생성자 함수에 메소드를 직접 갖게 된 구조

Array, Number 등의 생성자는 우측의 prototype에 메소드를 보관하지만

Object는 부모가 없기(?) 때문에 생성자함수에 메소드를 갖게 되었다.

보기 상당히 불편하지만 어쩔 수 없다.


코드로 이해하기

구조가 이상한 Object 생성자 말고 부모까지 가진 다른 일반적인 생성자함수의 prototype 접근에 대한 코드를 살펴보자

var arr = [1,2,3];
arr.toString = function() {
    return this.join('_');
}

console.log(arr.toString()); // 출력: 1_2_3
console.log(arr.__proto__.toString.call(arr));// 출력: 1,2,3
console.log(arr.__proto__.__proto__.toString.call(arr));// 출력: [object Array]

Object의 메소드인 toString을 배열에서 호출해보자

arr 인스턴스의 toString 메소드는 직접 수정한대로 출력이 된다.

그 위의 부모격인 Array, Object 생성자의 toString의 메소드는 수정되지 않은 원래의 기능으로 작동한다.

 

하지만 부모인 Array 생성자함수의 toString을 바꾸면,

arr라는 인스턴스는 부모의 메소드를 그대로 상속하기 때문에 다음과 같은 결과가 출력된다.

var arr = [1,2,3];
Array.prototype.toString = function() {
    return this.join('_');
}

console.log(arr.toString()); // 출력: 1_2_3
console.log(arr.__proto__.toString.call(arr));// 출력: 1_2_3
console.log(arr.__proto__.__proto__.toString.call(arr));// 출력: [object Array]

Object prototype도 바꿔보자

var obj = {
    a: 1,
    b: {
        c: 'c'
    }
};

Object.prototype.toString = function() {
    var res = [];
    for(var key in this) {
        res.push(key + ': ' + this[key].toString());
    }
    return '{' + res.join(', ') + '}';
}
console.log(obj.toString()); // 출력: {a: 1, b: {c: c}}

 

 

출처: Javascript 핵심 개념 알아보기 - JS Flow, 정재남 강사님, 코어자바스크립트