본문 바로가기
공부/JS

[Javascript] 프로토타입 알아보기 - 2

by Piva 2024. 2. 2.
  • 지난 글에 이어서, 코어 자바스크립트를 읽고 프로토타입에 대해 공부한 내용을 정리한다.

메서드 오버라이드(Method Override)

: 부모 역할을 하는 객체에 정의된 메서드를 재정의하는 것.

var Foo = function (bar) {
	this.bar = bar;
};

Foo.prototype.getBar = function () {
	return this.bar;
};

var foo = new Foo('hello');
foo.getBar = function () {
	console.log(this.bar + ', World!');
};

foo.getBar(); // hello, World! 가 출력된다

 

  • 생성자 Foo의 프로토타입에 getBar라는 메서드를 정의한다. 따라서 생성자 Foo 로 만들어진 객체는 getBar를 호출할 수 있다.
  • Foo 생성자로 생성된 객체 foo에서 getBar를 다시 정의한다. (메서드 오버라이드)
  • foo.getBar() 를 호출한다. 이 때, foo는 getBar를 재정의한 바가 있으므로, 프로토타입에 존재하는 부모 객체의 getBar가 아닌 자신의 getBar를 호출한다.
    • 이는 자바스크립트 엔진이 메서드/프로퍼티 호출 시 가장 가까운 대상인 자신의 메서드/프로퍼티를 먼저 검색하기 때문이다.
    • 원래 getBar인 부모 객체의 메서드를 호출하고 싶을 경우, __proto__ 로 직접 프로토타입에 접근하여 사용할 수 있다.

 

 

프로토타입 체인(Prototype Chain)

: 어떤 데이터의 __proto__ 내부에 다시 __proto__가 연쇄적으로 이어진 것.

 

  • 아래와 같이 배열을 선언했을 때, 프로토타입의 구조를 살펴보면 다음 그림과 같은 결과가 나온다.
var arr = new Array(1, 2, 3);

프로토타입 체인

  • 배열 arr는 __proto__로 Array의 프로토타입을 가리킨다.
  • 자바스크립트에서 배열, 함수 등은 모두 객체의 하위 분류에 속한다. 따라서 배열도 객체이며, 배열은 내부적으로 __proto__를 통해 Object의 프로토타입을 가리킨다.
  • 위와 같이 프로토타입이 연쇄적으로 이어지는 것을 프로토타입 체인이라고 한다.

 

 

프로토타입 체이닝(Prototype Chaining)

: 프로토타입 체인을 따라가며 프로퍼티를 검색하는 것. 즉, 자바스크립트의 특정 객체에서 접근하려는 프로퍼티나 메서드가 그 객체에 존재하지 않을 시, 해당 객체의 프로토타입(부모 역할을 하는객체의 프로토타입)으로 거슬러 올라가 찾고자 하는 메서드/프로퍼티를 찾는 것.

 

  • 기본 객체를 통해서도 프로토타입 체이닝을 확인할 수 있다.
var obj = {
    a: 1,
    b: 'hello',
};

console.log(obj.hasOwnProperty('a')); // true를 출력한다

 

  • obj에는 hasOwnProperty라는 메서드가 정의되어있지 않으나, 문제없이 호출이 가능하다.
  • 이는 obj에서 hasOwnProperty가 발견되지 않았기 때문에, 프로토타입 체인을 통해 obj의 프로토타입인 Object.prototype에 정의된 메서드인 hasOwnProperty를 호출했기 때문이다.
  • 위에서 살펴본 메서드 오버라이드와 비슷하다.
    • ex) 메서드 오버라이딩을 하지 않았다면, 원래 부모 객체의 프로토타입에 존재하는 메서드를 사용한다.

 

객체 전용 메서드의 예외사항

  • 어떤 생성자 함수든 그 prototype은 늘 객체이다. 따라서 프로토타입 최상단에 존재하는 것은 언제나 Object.prototype이다.
  • 따라서 Object.prototype에 존재하는 메서드는 모든 데이터 타입에서 접근이 가능하게 된다.
    • Object에서만 사용할 메서드를 만들고자 한다면, Object 자체에 static 메서드로서 구현해야 한다.
    • 반대로, Object.prototype의 메서드는 모든 데이터 타입에서 접근할 수 있기에 가장 범용적인 구조를 갖는다.
      • 어떤 데이터 타입이 호출하든 해당 메서드를 문제없이 사용할 수 있다!

 

 

다중 프로토타입 체인

  • 자바스크립트의 기본 데이터 타입은 일반적으로 프로토타입 체인이 1~2단계에서 끝나지만, 사용자가 데이터를 정의함에 따라 프로토타입 체인이 더 깊어질 수 있다.
var Foo = function () {
    var args = Array.prototype.slice.call(arguments);
    
    for (let i = 0; i < args.length; i++) {
    	this[i] = args[i];
    }
    this.length = args.length;
};

Foo.prototype = [];
  • 생성자 Foo함수는 length 프로퍼티를 갖고, 인자 여러 개를 받아 인덱스를 붙여 저장한다는 점에서 유사 배열 객체이다.
  • 따라서 Foo의 프로토타입으로 Array를 연결하면, Array와 Object의 prototype에 있는 메서드를 사용할 수 있다.
    • 이 때, 프로토타입 체인은 [Foo] - [Array] - [Object]의 3단계가 된다.