[JS] 프로토타입 체이닝

daybyday·2021년 1월 11일
0

Javascript

목록 보기
8/15
post-thumbnail

프로토타입 체이닝이란?

자바스크립트는 특정 객체의 프로퍼티나 메소드에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티 또는 메소드가 없다면 [[Prototype]]이 가리키는 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티나 메소드를 차례대로 검색한다. 이것을 프로토타입 체인이라 한다.


prototype 프로퍼티 vs [[Prototype]]

prototype 프로퍼티와 모든 객체의 부모를 나타내는 내부 프로퍼티인 [[Prototype]]는 다른 것이다.

두 프로퍼티 모두 프로토타입 객체를 가리킨다는 공통점이 있지만 관점이 다르다. 모든 객체에 존재하는 내부 프로퍼티인 [[Prototype]]은 객체 자신의 부모 역할을 하는 프로토타입 객체를 가리키고, prototype 프로퍼티이 함수가 생성자로 사용될 때, 이 함수로 생성된 객체의 부모 역할을 하는 프로토타입 객체를 가리킨다.

즉, 자바스크립트에서는 함수를 생성할 때, 함수 자신과 연결된 프로토타입 객체를 동시에 생성하고, 이 둘은 서로를 참조하게 된다.

결과적으로 prototype 프로퍼티와 [[Prototype]]이 가리키는 프로토타입 객체는 같지만 관점이 다르다는 것을 기억하자.

//Person 생성자 함수
function Person(name){
	this.name = name;
}

let foo = new Person('foo');

console.dir(Person);
console.dir(foo);

위 코드를 크롬 브라우저에서 실행한 결과 (__proto__[[Prototype]]이다)



객체 리터럴 방식으로 생성된 객체의 프로토타입 체이닝

let myObject = {
	name: 'foo',
  	sayName: function(){
    		console.log('My name is ' + this.name);
   	}
}

myObject.sayName(); // ----- 1
console.log(myObject.hasOwnProperty('name')); // ----- 2
console.log(myObject.hasOwnProperty('nickName')); // ----- 3
myObject.sayNickname(); // ----- 4

위 코드를 크롬 브라우저에서 실행한 결과


myObject는 name 프로퍼티와 sayName() 메서드를 가진 객체이다. myObject에 nickname이라는 프로퍼티는 없으므로, 3번의 결과는 false가 나온다. 그리고 4번의 결과도 에러가 나는 것이 당연한 결과로 보인다.

그런데, myObject에는 hasOwnProperty()라는 메서드가 없음에도 2, 3번이 에러없이 출력된 것을 볼 수 있다.

객체 리터럴 방식으로 생성된 객체는 Object()라는 내장 생성자 함수로 생성된 것이다. 따라서, Object()의 prototype 프로퍼티가 가리키는 Object.prototype 객체가 [[Prototype]]링크로 연결되어 myObject의 부모객체가 된 것이다.

2, 3번에서 myObject.hasOwnProperty() 메서드를 호출했지만 myObject에는 그런 메서드가 없다. 그러면 myObject는 [[Prototype]] 링크를 따라 부모 역할을 하는 Object.prototype 객체 내에 해당 메서드가 있는지 검색한다. Object.prototype 객체는 자바스크립트 표준 API인 hasOwnProperty() 메서드를 가지고 있으므로, myObject 객체에서도 자신의 프로퍼티처럼 사용할 수 있게된 것이다.

4번에서 호출한 메서드는 myObject, Object.prototype 객체 모두 갖고있지 않은 메서드이므로 오류가 발생하는 것이다.


생성자 함수로 생성된 객체의 프로토타입 체이닝

//Person 생성자 함수
function Person(name, age, hobby){
	this.name = name,
      	this.age = age,
      	this.hobby = hobby
}

let foo = new Person('foo', 30, 'tennis');  // ------- 1

//프로토타입 체이닝
console.log(foo.hasOwnProperty('name')); // true // ------- 2

//Person.prototype 객체 출력
console.dir(Person.prototype); // ------- 3

  1. foo 객체의 생성자 함수는 Person() 함수이다. 따라서 foo의 프로토타입 객체는 Person 생성자 함수의 prototype 프로퍼티가 가리키는 Person.prototype 객체이다.

  2. foo 객체에서 hasOwnProperty() 메서드를 호출하고 있다. 그러나 foo와 Person.prototype 모두 hasOwnPropety()라는 메서드는 가지고 있지 않다.

    모든 자바스크립트 객체는 Object.prototype을 프토로타입 객체로 가진다. Person.prototype도 객체이므로, Object.prototype에 있는 프로퍼티들을 사용할 수 있는 것이다.

프로토타입 체이닝의 종점

자바스크립트에서 프로토타입 체이닝의 종점은 Object.prototype 객체이다. 모든 자바스크립트 객체는 프로토타입 체이닝으로 Object.prototype 객체가 가진 프로퍼티와 메서드에 접근하고, 서로 공유가 가능하다.

객체 리터럴 방식이나 생성자 함수 방식이나 결국 Object.prototype에서 프로토타입 체이닝이 끝나는 것을 볼 수 있다.



참조

인사이드 자바스크립트 4.5 프로토타입 체이닝

0개의 댓글