코어자바스크립트 6장<프로토타입>

김정현·2021년 2월 5일
0
post-thumbnail

1. 프로토타입의 개념 이해

자바스크립트는 프로토타입 기반 언어입니다. 클래스 기반의 언어에서는 상속을 사용하지만, 프로토타입 기반 언어에서는 어떤 객체를 원형으로 삼고 이를 복제(참조)함으로써 상속과 비슷한 효과를 얻습니다.

1-1) constructor, prototype, instance

var instance = new Constructor();
  1. 어떤 생성자 함수(Constructor)를 new 연산자와 함께 호출하면
  2. Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스(instance)가 생성됩니다.
  3. 이때 instance에는 proto라는 프로퍼티가 자동으로 부여됩니다.
  4. 이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조합니다.

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

var suzi = new Person('Suzi', 28);
 suzi.getName();    // Suzi
 var iu = new Person('Jieun', 28);
 iu.getName();      // Jieun

proto는 생략 가능한 프로퍼티이다. 때문에 생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있다.
=> new 연산자로 Constructor를 호출하면 instance가 만들어지는데, 이 instance의 생략 가능한 프로퍼티인 proto는 Constructor의 prototype을 참조한다.

1-2) constructor 프로퍼티

생성자 함수의 프로퍼티인 prototype 객체 내부에는 constructor라는 프로퍼티도 존재합니다. 인스턴스의 proto 객체 내부에도 마찬가지입니다. 이 프로퍼티는 단어 그대로 원래 생성자 함수(자기 자신)를 참조합니다. 이를 가지고 있는 이유는 인스턴스로부터 그 원형이 무엇인지를 알 수 있는 수단이기 떄문입니다.

2. 프로토타입 체인

2-1) 메서드 오버라이드

prototype 객체를 참조하는 proto를 생략하면 인스턴스는 prototype에 정의된 프로퍼티나 메소드를 자신의 것처럼 사용할 수 있습니다. 그런데 만약 인스턴스가 동일한 이름의 프로퍼티 또는 메소드를 가지고 있는 상황이라면?

var Person = function (name) {
  this.name = name;
}

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

var iu = new Person('지금');
iu.getName = function () {
  return '바로 ' + this.name
}

console.log(iu.getName());	//바로 지금

1.여기서는 iu.proto.getName이 아닌 iu 객체에 있는 getName 메소드가 호출됐습니다.
2. 즉, proto에 있는 메소드는 자신에게 있는 메소드보다 검색 순서에서 밀려 호출되지 않은 것입니다.

이러한 현상을 메소드 오버라이드라고 합니다. 메소드 위에 메소드를 덮어씌웠다는 표현입니다.

만일 인스턴스를 바라보도록 바꿔주고 싶다면 call 이나 apply를 사용하면 된다.

console.log(iu.__proto__.getName.call(iu)); // 지금

2-2) 프로토타입 체인

어떤 데이터의 proto프로퍼티 내부에 다시 proto프로퍼티가 연쇄적으로 이어진 것을 프로토타입 체인이라 하고, 이 체인을 따라가며 검색하는 것을 프로토타입 체이닝이라고 합니다.

이는 메소드 오버라이드와 동일한 맥락입니다. 어떤 메소드를 호출하면 자바스크립트 엔진은 자신의 프로퍼티를 검색해서 원하는 메소드가 있으면 그 메소드를 실행하고 없는 경우 proto를 검색해서 있으면 그 메소드를 실행하는 방식으로 진행합니다.

var arr = [1,2];
Array.prototype.toString.call(arr);	//1,2
Object.prototype.toString.call(arr);	//[object Array]
arr.toString();	//1,2

arr.toString = function () {
  return this.join('_');
};
arr.toString();	//1_2

0개의 댓글