기술면접을 준비하는 과정에서 자바스크립트의 프로토타입 개념에 대해 공부하였고 프로토타입 개념에 대해 정리한다. 이 정리글은 코어 자바스크립트(정재남)를 참고하여 작성하였다.
자바스크립트는 프로토타입 기반 언어로, 어떤 객체를 프로토타입으로 삼고 이를 참조함으로써 상속과 비슷한 효과를 얻는다.
var instance = new Constructor();
이 코드는 다음과 같이 이해할 수 있다.
__proto__ 라는 프로퍼티가 자동으로 부여된다.__proto__ 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조한다.
prototype프로퍼티와__proto__프로퍼티의 관계가 프로토타입 개념의 핵심이다.
prototype 프로퍼티는 객체이고, 이를 참조하는 __proto__ 프로퍼티 역시 객체이다.prototype 내부에는 인스턴스가 사용할 메서드를 저장한다.__proto__ 프로퍼티를 통해 prototype 내부에 저장된 메서드에 접근할 수 있다.var Person = function (name) {
this._name = name;
};
Person.prototype.getName = function() {
return this._name;
};
Person 생성자 함수의 prototype 프로퍼티에 getName 메서드를 추가하였다. 이제 Person의 인스턴스는 __proto__ 프로퍼티를 통해 getName 메서드를 호출할 수 있다.
var cabbage = new Person('cabbage');
console.log(cabbage.__proto__.getName()); // undefined
'cabbage'가 아닌 'undefined'가 출력되었다. 이것은 자바스크립트의 this 바인딩 때문이다. 어떤 함수를 메서드로서 호출하는 경우 메서드 바로 앞의 객체가 곧 this가 된다.
cabbage.__proto__가 된다.__proto__도 객체이고 이 객체 내부에는 name 프로퍼티가 존재하지 않으므로 undefined가 반환된다.따라서 this를 인스턴스로 하려면 __proto__ 없이 인스턴스에서 곧바로 메서드를 사용한다.
var cabbage = new Person('cabbage');
console.log(cabbage.getName()); // cabbage
__proto__를 생략하면 this는 인스턴스인 cabbage가 된다.이 코드가 동작하는 이유는 __proto__ 프로퍼티는 생략 가능하기 때문이다.
__proto__를 생략하면 this는 인스턴스를 가리킨다.__proto__를 생략하지 않으면 this는 인스턴스.__proto__를 가리킨다.인스턴스.__proto__에 있는 getName 메서드를 실행하지만 this는 인스턴스를 가리키게 되었다.__proto__가 자동으로 부여되고, __proto__는 Constructor의 prototype 프로퍼티를 참조한다.__proto__는 생략 가능하도록 구현되어 있다. 따라서 인스턴스는 Constructor의 prototype에 있는 메서드나 프로퍼티를 자신의 것처럼 사용할 수 있다.생성자 함수 Array와 인스턴스를 통해 생성자 함수의 prototype 프로퍼티와 인스턴스의 __proto__ 프로퍼티의 관계를 살펴보자.
var arr = [1, 2];
console.dir(arr); // 브라우저 콘솔창에서 확인하기
console.dir(Array); // 브라우저 콘솔창에서 확인하기

__proto__ 프로퍼티([[Prototype]])는 Array 생성자 함수의 prototype 프로퍼티를 참조한다.__proto__ 프로퍼티는 생략 가능하게 설계되어 있으므로 인스턴스가 마치 자신의 메서드인 것처럼 Array.prototype의 메서드들을 사용할 수 있다.
MDN에서 배열 메서드들을 보면 항상 Array.prototype이라는 것이 붙어 있었는데, 이게 왜 붙어 있는지 그 이유에 대해 알 수 있었다.
배열 인스턴스는 배열 메서드를 자신의 메서드처럼 사용하지만 결국 생성자 함수 Array의 prototype 프로퍼티에 있는 메서드들을 사용하는 것이다.