자바스크립트는 프로토타입을 기반으로 상속을 구현한다.
모든 객체는 [[prototype]] 이라는 내부 슬롯을 가지고 있다. [[prototype]] 에 직접적으로 접근은 어렵지만 __proto__
라는 접근자 프로퍼티를 통해 간접적으로 접근할 수 있고 __proto__
을 통해 간접적으로 자신의 상위 프로토타입을 알 수 있다.
__proto__
가 null 인 경우는 프로토타입 체인의 종점이다.
프로토타입을 통해 상속이 가능해진다.
만약 JS가 상속을 지원하지 않는 언어였다면
function Circle(radius){
this.radius = radius;
this.getArea = function(){
return Math.PI * this.radius ** 2;
};
}
const new Circle = new Circle(3);
const new Circle = new Circle(4);
겹치는 getArea() 라는 메서드를 Circle1, Circle2 에 중복 생성시켰어야 한다. 하지만, 프로토타입을 통해 상속이 가능하기 때문에 getArea() 메서드를 Circle.prototype에 담아주면 Circle에는 자신의 식별자만 가지면 된다.
Circle.prototype.getArea = function(){
return Math.PI * this.radius ** 2 ;
}
우와 같은 방법으로 getArea라는 메서드를 Circle.prototype 에 추가해주면 Circle.prototype에 공통적으로 getArea 메서드를 갖고, Circle1 과 Circle2 는 각자의 radius 만 가질 수 있다.
자바스크립트 엔진은 프로토타입 체인을 통해 프로퍼티/메서드를 검색하고, 스코프체인을 통해 식별자를 검색한다.
me.hasOwnProperty('name');
me 는 hasOwnProperty
라는 메서드를 가지고 있지만 프로토타입을 통해 상속
을 받았기 때문에 hasOwnProperty
메서드를 사용할 수 있다.
자바스크립트 엔진에서는 어떤 과정을 거쳐 메서드를 검색할까?
hasOwnProperty
가 없기 때문에 프로토체인을 따라 메서드를 검색한다. me 객체 상위 프로토타입은 Person.prototype에도 hasOwnProperty
가 존재하지 않으니 Person.prototype의 프로토타입을 체크하여 Object.prototype에서 hasOwnProperty
메서드를 찾는다.만약 Object.prototype 에 그 메서드가 없어도 오류 를 출력하는 것이 아닌 undefined 를 출력한다.
function Person (name) {
this.name = name;
}
Person.prototype.sayHello=function(){
console.log(` hi my name is ${this.name}`);
};
const me=new Person('lee');
프로토타입 프로퍼티를 삭제하기 위해 (이럴 일이 없게끔 처음부터 삭제할 프로퍼티를 안만드는 것이 best다.) me를 통해 접근하는 것이 아니라, Person.prototype.sayHello
로 직접 접근이 가능하다는 것이다.
삭제 뿐만 아니라 자신의 상위 프로토타입을 직접 지정해줄 수 있다.
이렇게 상속관계를 동적으로 변경할 수 있다는 것은 가독성을 떨어 뜨리고, 추가적인 연결 ― Person 과 Person.prototype 의 연결이 끊어진 경우 ― 을 도와주는 코드가 필요하다. (상속 관계를 바꾸는 것은 대부분 안티패턴)
+ 상속관계이기 때문에 하나 잘못 건들이면 이미 생성되었고, 생성될 객체에게 모두 영향을 준다.
프로토타입을 쓰면 this를 써야하는데 자바스크립트의 this는 함수가 호출되는 방식에 따라 동적으로 바인딩된다. 그래서 문제점이다.
- 일반 함수로 호출되는 경우 : 전역 객체가 this다.
- 메서드로 호출되는 경우 : 메서드를 호출한 객체가 this다.
- 생성자 함수로 호출되는 경우 : this는 생성자 함수가 생성 할 인스턴스가 된다.
코드 내에서 this가 어떤 this를 의미하는지 찾아야하기 때문에 가독성이 떨어질 수 있다.
당연한 이야기지만 시기에 맞춰 잘 이용한다. 상속이 필요하지 않는다면 굳이 프로토타입으로 구현하지 않아도 된다. ― 상속이 필요할 때가 그렇게 많았나?! 라는 생각이 있다. ―
reference |
poiemaweb - 모던자바스크립트
MeetUp - 쉽게 이해하는 자바스크립트 프로토타입 체인
[JS 프로토타입] 자바스크립트의 프로토타입 훑어보기