- 지난 글에 이어서, 코어 자바스크립트를 읽고 프로토타입에 대해 공부한 내용을 정리한다.
메서드 오버라이드(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단계가 된다.
'공부 > JS' 카테고리의 다른 글
함수형 자바스크립트 훑어보기 (0) | 2024.11.26 |
---|---|
[Javascript] 프로토타입 알아보기 - 1 (0) | 2024.01.24 |
[Javascript] 콜백 함수 알아보기 (1) | 2024.01.21 |
[Javascript] 클로저 알아보기 - 2 (1) | 2024.01.08 |
[Javascript] 클로저 알아보기 - 1 (1) | 2024.01.05 |