191023_TIL(프로토타입 메소드 이해하기)

오늘은 친구가 지원한 회사에서 테스트로 나온 문제를 공유해주어서 풀어보았다.

1
2
// 문제. 아래 코드와 같이 "."으로 계속해서 이어지는 함수를 작성하시오.
add(4).add(5).subtract(3) // 6

…?

처음에 문제를 보았을 때는 이게 뭐지?? 라는 생각이 들었다.

마음을 가다듬고 찬찬히 문제를 들여다보니 프로퍼티 값에 접근하는 방법인 마침표 표기법이 보였다.

아! 객체의 메소드를 이용하는 것이구나라고 단순히 생각하여 자바스크립트에서는 함수도 객체이기 때문에 아래 코드와 같이 함수에서 객체의 메소드를 정의하는 방법을 생각해보았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const add = (n) => {
let result = 0;
result += n;
return {
add(n) {
result += n;
return result;
}
};
};

const sum = add(4).add(5);
sum; // 9

하지만 위 방법으로는 문제에서 요구하는 계속해서 이어지는 함수를 만들 수는 없었다.

그렇다면 어떻게 해야 계속해서 객체의 메소드를 호출할 있을까?

고민을 거듭한 결과 불현듯 프로토 타입 메소드가 떠올랐다. 프로토 타입 메소드란 프로토 타입 체인 상에 존재하는 메소드이다.

자바스크립트는 특정 객체의 메소드에 접근하려고 할 때 해당 객체에 접근하려는 메소드가 없다면 [[Prototype]]이 가리키는 링크를 따라 상위 프로토타입 객체의 메소드를 프로토타입 체인상에서 차례대로 검색한다. 이를 이용하면 아래와 같이 코드를 작성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
let result = 0;

Object.prototype.add = function(n) {
result += n;
return result;
};

Object.prototype.subtract = function(n) {
result -= n;
return result;
};

add(4).add(5).subtract(3);// 6

전역변수를 선언한 것이 마음에 들지 않지만 원했던 결과가 제대로 나온다.

위 코드를 해석하기 위해서는 우선 아래의 사실을 인지해야 한다.

프로토타입 체인의 종점, 즉 프로토타입 체인의 최상위 객체는 Object.prototype이며 이 객체의 프로퍼티와 메소드는 모든 객체에게 상속된다.

1
2
// 프로토타입 체인 상 종점에 존재하기 때문에 Object.prototype.__proto__는 null이다.
Object.prototype.__proto__ // null
1
2
// 브라우저 환경에서의 전역객체인 window도 프로토타입 체인에 존재하며 따라서Object.prototype의 프로퍼티와 메소드를 상속받아서 사용할 수 있다.
window.__proto__.__proto__.__proto__.__proto__ === Object.prototype //true

그런데 add(), subtract() 메소드는 number 타입의 원시값을 반환하는데 어떻게 프로토타입 메소드를 상속 받아서 사용할 수 있는 것일까?

string ,number 타입 등의 원시값 뒤에 마침표 표기법이나 대괄호 표기법과 같이 프로퍼티의 값에 접근하는 표기법을 사용하면 순간 임시 객체가 생성되는데 이를 래퍼 객체라고 한다.

즉, 래퍼 객체가 일시적으로 생성되면 프로토타입 메소드를 상속 받아서 사용할 수 있는 것이다.

참고 자료

poiemaweb 프로토타입

Share