-
[JavaScript] 프로토타입 체이닝 2 : 프로토타입 변경 및 프로토타입 체이닝카테고리 없음 2020. 2. 14. 20:59
* 함수 생성과 프로토타입 객체
자바스크립트에서는 함수가 생성될 때, 프로토타입 객체도 함께 생성된다. 함수와 프로토타입은 각각 가지고 있는 prototype, constructor 프로퍼티를 통해 서로 연결된다. 코드로 나타내면 아래와 같다.
// Constuctor Function function Car(brand){ this.brand = brand }; // Prototype Object : 함수 생성시 같이 생성됨 Car.prototype = { constructor : Car }
함수 Car가 생성되며 의 프로토타입 객체가 함께 생성된다. 객체 안에는 constructor 프로퍼티가 들어있다. ( 실제 찍어보면 __proto__ 가 함께 있는데, 이는 상위 객체인 Object.prototype 과 연결되어 있는 것이다. 설명에서는 생략한다) Car.prototype은 프로토타입 객체를 가리키며, Car.prototype.constructor 는 함수를 가리킨다.
* 디폴트 프로토타입 변경
함수 생성시에 함께 만들어진 프로토타입 객체를 디폴트 프로토타입이라고 한다. 자바스크립트의 특징은, 함수와 연결된 디폴트 프로토타입 객체를 다른 객체로 변경하는 것이 가능하다는 것이다.
코드로 예를 들면 아래와 같다.
// Constructor Function function Car(brand){ this.brand = brand }; // 이 시점의 Prototype Object : Car.prototype = { constructor : Car }; var scooter = new Car('blue'); console.log(scooter.price); //undefined <1> Car.prototype = { price : 1000}; console.log(Car.prototype.constructor) // Object() <2> var bike = new Car('green'); console.log(bike.price) //1000 <3> console.log(bike.constructor) // Object.prototype.constructer (=== Object()) <4> console.log(scooter.price) //undefined <5> console.log(scooter.constructor) //Car <6>
먼저 Car 라는 함수가 선언되었다. 이와 함께 디폴트 프로토타입 객체가 함께 생성된다. 둘은 각자의 프로퍼티로 이어져 있다. 이어서, 생성자함수 Car를 통해 그 인스턴스인 scooter 객체를 만들어낸다. 이 때 scooter 는 __proto__ 프로퍼티를 통해 디폴트 프로토타입과 연결되어 있다. 이를 그림으로 나타내면 아래와 같다.
디폴트 프로토타입을 변경하기로 한다. price라는 프로퍼티를 가진 새로운 객체를 만들어 Car의 prototype 프로퍼티와 이어준다. 디폴트 프로토타입과의 연결이 끊기고, 새로 생성된 객체가 Car 의 프로토타입이 된다.
디폴트 프로토타입이 변경된 이후 생성자함수 Car로 bike 라는 인스턴스를 만든다. 이 때 bikes는 __proto__를 통해 새로 할당된 프로토타입과 연결된다. 이를 그림으로 나타내면 다음과 같다.
scooter와 bike 는 모두 같은 생성자함수인 Car 에 의해 만들어진 인스턴스들이다. 그러나 __proto__를 통해 이어져있는 프로토타입은 서로 다르다.
scooter의 __proto__는 처음 함수가 만들어질 당시의 디폴트 프로토타입(default prototype)과 연결되어 있다. 기존 프로토타입에는 constructor 프로퍼티만 존재한다. 따라서 scooter.price 의 값은 undefined가 된다 <5>
그러나 bike 는 디폴트 프로토타입이 변경된 이후에 생성된 인스턴스이기 때문에, bike의 __proto__는 새로 생성된 프로토타입(new prototype)과 연결된다. 따라서 price 프로퍼티에 접근해 이를 사용하는 것이 가능해진다. <3>* 프로토타입 체이닝
그렇다면 bike.constructor 는 어떤 값이 나올까? (<4>)
유의할 점은 새로 생성된 프로토타입(new prototype)에는 constructor 프로퍼티가 없다는 점이다. 따라서 bike.constructor가 bike 객체 내부에도, 그 프로토타입(new prototype)에도 없다.
중요한 것은 모든 객체는 그 뿌리(__proto__)를 타고 가면 Object.prototype 과 연결되어 있다는 점이다. 따라서 프로토타입(new prototype) 역시 __proto__를 가지고 있으며 이는 Object.prototype 과 연결되어 있다. 프로토타입 체이닝을 통해 .constructor 프로퍼티를 검색할 수 있는 조건이 충족된다.
Object.prototype은 constructor 프로퍼티로 Object()를 가지므로, 이 값을 가져올 수 있다. 따라서 프로토타입 체이닝을 통해 bike.constructor는 Object() 가 된다.
반면, scooter는 여전히 ___proto___ 프로퍼티를 통해 기존 프로토타입과 연결되어 있다. 그리고 해당 프로토타입에는 constructor 프로퍼티가 존재하며, 이는 함수 Car와 연결되어 있다. 따라서 scooter.constructor 는 Car() 함수가 된다. <6>*reference : <인사이드 자바스크립트>