본문 바로가기

Frontend/JavaScript

[JavaScript] 코어 자바스크립트 6장 - 프로토타입

반응형

아래 책을 읽고 정리한 내용입니다.

http://www.yes24.com/Product/Goods/78586788

 

코어 자바스크립트 - YES24

자바스크립트의 근간을 이루는 핵심 이론들을 정확하게 이해하는 것을 목표로 합니다최근 웹 개발 진영은 빠르게 발전하고 있으며, 그 중심에는 자바스크립트가 있다고 해도 결코 과언이 아니

www.yes24.com

 

 

💡 프로토타입 기반 언어인 자바스크립트에서는 객체를 원형으로 삼고 이를 참조함으로써 상속과 비슷한 효과를 얻는다.

 

프로토타입 개념 이해하기

  • new 연산자로 Constructor를 호출하면 인스턴스가 만들어지는데, 이 인스턴스의 프로퍼티인 __proto__Constructorprototype을 참조한다.
  • 생성자 함수의 prototype에 어떤 메서드가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티를 사용할 수 있다.
  • prototype은 객체이며, 이를 참조하는 __proto__ 역시 객체이다.

 

코드를 통해 자세히 알아보자.

  • Person이라는 생성자 함수의 prototype에 getName이라는 메서드를 지정했다.
  • Person의 인스턴스인 suzi는 __proto__를 통해 getName을 호출할 수 있다.
  • 그런데 왜 undefined 출력될까?
    • this 바인딩이 대상이 잘못되었기 때문이다.
    • getName은 메서드로서 호출되어 바인딩 대상은 suzi가 아니라 suzi.__proto__이고, suzi.__proto__에는 _name이 없기 때문에 undefined가 출력되는 것이다.
  • __proto__는 생략 가능한 프로퍼티이므로, suzi.getName()처럼 바로 호출할 수 있고 이때 Suzi가 정상적으로 출력된다.
var Person = function(name) {
    this._name = name;
};

Person.prototype.getName = function() {
    return this._name;
};

var suzi = new Person('Suzi');
console.log(suzi.__proto__.getName()); //undefined
console.log(suzi.getName()); //Suzi

 

내장 생성자 함수 Array를 통해 확인해 보자.

  • Array의 prototype에 있는 메서드가 arrInstance의 __proto__에 들어 있는 것을 볼 수 있다.
const arrInstance = new Array();

console.dir(Array);
console.dir(arrInstance);

좌) Array 출력 -> prototype, 우) arrInstance 출력 -> [[Prototype]](__proto__)

 

cf) ES5.1 명세에는 __proto__가 아니라 [[prototype]]이라는 명칭으로 정의되어 있다.

 

정리하자면, 프로토타입 개념은 다음과 같다.

  • 자바스크립트는 함수에 자동으로 객체 prototype 프로퍼티를 생성해 놓는데, 해당 함수를 생성자 함수로서 사용할 경우, 그로부터 만들어진 인스턴스에는 숨겨진 프로퍼티 __proto__가 자동으로 생성되며, 이 프로퍼티는 생성자 함수의 prototype을 참조한다.
  • __proto__는 생략이 가능하기 때문에 인스턴스는 생성자 함수의 prototype에 있는 메서드를 마치 자신의 것처럼 접근할 수 있다.

책의 그림 6.3과 6.6의 도식을 보면 이해하기 쉽다!

 

 

Constructor 프로퍼티

  • 생성자 함수의 프로퍼티인 prototype 객체 내부에는 constructor라는 프로퍼티가 있다. (인스턴스의 __proto__도 마찬가지)
  • 이 프로퍼티는 원래의 생성자 함수(자기 자신)를 참조한다.
  • 인스턴스로부터 그 원형이 무엇인지 알 수 있는 수단이다. (상속 흉내가 가능해진 측면)

 

다음 각 줄은 모두 동일한 대상(생성자)을 가리키다.

[Constructor]
[Constructor].prototype.constructor
[instance].constructor
[instance].__proto__.constructor
Object.getPrototypeOf([instance]).constructor
const instance = new Array();

//모두 [Function: Array]를 출력
console.log(Array);
console.log(Array.prototype.constructor);
console.log(instance.constructor);
console.log(instance.__proto__.constructor);
console.log(Object.getPrototypeOf(instance).constructor);

 

 

프로토타입 체인

  • 어떤 데이터의 __proto__ 프로퍼티 내부에 다시 __proto__ 프로퍼티가 연쇄적으로 이어진 것을 프로토타입 체인이라 하고, 이 체인을 따라가며 검색하는 것을 프로토타입 체이닝이라고 한다.
  • 어떤 메서드를 호출하면 자바스크립트 엔진은 데이터 자신의 프로퍼티를 검색해서 원하는 메서드가 있으면 그 메서드를 실행하고, 없으면 __proto__를 검색한다. 메서드가 있을 경우 그 메서드를 실행하고, 또 없으면 다시 __proto__를 검색한다.
  • 자바스크립트의 모든 데이터의 프로토타입 체인 끝에는 Object.prototype가 있다. prototype이 객체이기 때문이다.
  • 프로토타입 체인은 무한대의 단계(다중 프로토타입 체인)로 확장이 가능하다.

 

cf) 메서드가 오버라이딩될 때(인스턴스에서 동일한 메서드를 가지고 있는 경우), 원본은 그대로 둔다. 따라서 프로토타입 체인을 통해 원본에도 접근이 가능하다. 

 

 

 

반응형