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

Yongwoo Cho·2022년 6월 21일
0

TIL

목록 보기
97/98
post-thumbnail

6장 - 프로토타입

어떤 생성자 함수를 new 연산자와 함께 호출하면 Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스가 생성된다. 이때 인스턴스에는 __proto__ 라는 프로퍼티가 자동으로 부여되는데 이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조한다.

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

Person.prototype.getName = function () {
  return this._name;
};
var suzi = new Person("Suzi");
suzi.__proto__.getName(); // undefined
suzi.getName(); // Suzi

undefined가 나왔다는 것은 이 변수가 '호출할 수 있는 함수'에 해당한다는 것을 의미한다. 만약 실행할 수 없는, 즉 함수가 아닌 다른 데이터 타입이었다면 TypeError가 발생했을 것이다.

❓ 왜 undefind가 출력되나

👉 this에 바인딩된 대상이 잘못 지정됐기 때문이다. this는 suzi가 아닌 suzi.__proto__라는 객체이기 때문에 undefined가 반환된 것이다.

__proto__는 생략 가능한 프로퍼티다. 따라서 생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있게 된다.

var arr = [1, 2];
arr.forEach(function () {}); // 정상
Array.isArray(arr); // 정상 true
arr.isArray(); // ❌ TypeError : arr.isArray is not a function

Array를 new 연산자와 함께 호출해서 인스턴스를 생성하든, 그냥 배열 리터럴을 생성하든, 어쨋든 인스턴스인 [1, 2]가 만들어진다. 이 인스턴스의 __proto__는 Array.prototype을 참조하는데 __proto__가 생략 가능하도록 설계돼 있기 때문에 인스턴스가 push, pop, forEach 등의 메서드를 마치 자신의 것처럼 호출할 수 있다.

❗ 한편 Array의 prototype 프로퍼티 내부에 있지 않은 from, isArray등의 메서드들은 인스턴스가 직접 호출할 수 없다. 이들은 Array 생성자 함수에서 직접 접근해야 실행이 가능하다.

✔️ constructor 프로퍼티

생성자 함수의 프로퍼티인 prototype 객체 내부에는 constructor라는 프로퍼티가 있다. 인스턴스의 __proto__ 객체 내부에도 마찬가지이다. 이 프로퍼티는 단어 그대로 원래의 생성자 함수를 참조한다.

var arr = [1, 2];
Array.prototype.constructor === Array; // true
arr.__proto__.constructor === Array; // true
arr.constructor === Array; // true

모두 동일한 대상을 가리킨다.

[Constructor][instance].__proto__.constructor[instance].constructor;
Object.getPrototypeOf([instance]).constructor[Constructor].prototype
  .constructor;

모두 동일한 객체(prototype)에 접근할 수 있다.

[Constructor].prototype[instance].__proto__[instance];
Object.getPrototypeOf([instance]);

✔️ 프로토타입 체인

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()); // 바로 지금

iu.__proto__.getName이 아닌 iu 객체에 있는 getName 메서드가 호출되는데 이러한 현상을 메서드 오버라이드라고 한다. 자바스크립트 엔진이 getName 이라는 메서드를 찾는 방식은 가장 가까운 대상인 자신의 프로퍼티를 검색하고, 없으면 그다음으로 가까운 대상인 __proto__를 검색하는 순서로 진행된다.

모든 객체의 __proto__에는 Object.prototype이 연결된다. 어떤 데이터의 __proto__ 프로퍼티 내부에 다시 __proto__ 프로퍼티가 연쇄적으로 이어진 것을 프로토타입 체인이라 하고, 이 체인을 따락며 검색하는 것을 프로토타입 체이닝이라고 한다. 프로토타입 체인상 가장 마지막에는 언제나 Object.prototype이 있다.

❗ 하지만 예외적으로 Object.create를 이용하면 Object.prototype의 메서드에 접근할 수 없는 경우가 있다. Object.create(null)은 __proto__가 없는 객체를 생성한다.

profile
Frontend 개발자입니다 😎

0개의 댓글