javascript 는 프로토타입 기반의 언어이다. 즉, js 자체는 객체 지향 프로그래밍 언어가 아니기 때문에, 여러 방식을 통해 OOP를 구현하려는 시도가 있어왔다. ES6 로 넘어오며 class, subclass 개념을 등장시켜 적극적으로 객체 지향을 지원하기 전까지, OOP 구현에 가장 자주 쓰였던 방식은 pseudoclassical 방식이며 아직도 예전 코드에 많이 남아있으므로 legacy 차원에서 배워 둘 의의가 있다.
수도클래시컬. 사전을 찾아보면 pseudo 는 '가짜의' 라는 의미를 지니는데 대충 해석해보면, 가짜로 class 개념을 흉내내는 방식이라는 뜻인 것 같다. 야매로 class 흉내내기. 이렇게 뜻을 이해하고 읽으면, 혀가 덜 꼬이는 것 같은 착각을 즐길 수 있다.
아래 코드를 통해, 이 방식의 필수 3 step 을 소개한다. 우리는 냉장고 함수의 모든 속성을 상속받은 김치냉장고 함수를 만들고자 한다.
function Fridge (brand, price) {
this.brand = brand;
this.price = price;
}
function KimchiFridge (...args) {
// step 1
Fridge.apply(this, args)
}
// step 2
KimchiFridge.prototype = Object.create(Fridge.prototype);
// step 3
KimchiFridge.prototype.constructor = KimchiFridge;
[STEP 1] 자식 생성자 함수 안에서 call/apply 를 통해 부모 생성자 함수와 연결시킨다.
[STEP 2] 자식 생성자 함수의 prototype 객체를 Object.create 메소드를 통해 부모 생성자 함수의 prototype 과 연결시킨다.
[STEP 3] 자식 생성자 함수의 constructor 를 자기 자신으로 재할당해준다.
안 된다. 굳이 Object.create 를 쓴 데에는 다 이유가 있다. 아래 두 코드가 다른 점이 뭘까?
// wrong
KimchiFridge.prototype = Fridge.prototype;
// correct
KimchiFridge.prototype = Object.create(Fridge.prototype);
윗 줄의 코드처럼 부모 생성자 함수의 prototype 을 그~대로 갖다 붙일 경우, 부모 생성자 함수의 주소값까지 그대로 가져와서 두 함수가 아예 동일시되어 버린다. 즉, 두 함수가 연동되어 김치냉장고에 속성을 추가하면 냉장고 함수에도 속성이 추가되어 결과적으로 그냥 동일한 함수가 되어버리는 것이다.
우리가 만들고 싶은 건, 부모 생성자 함수에 속성이 추가되면 자식 생성자 함수들도 언제든 그걸 공유받을 수 있지만, 각 자식 생성자 함수들에는 뭐가 추가되어도 부모 생성자 함수는 영향받지 않는 별개의 함수를 만들고 싶은 것이다. 그걸 얕은 복사를 실행하는 Object.create 가 실행해준다. Object.create 는 새로운 주소값을 가지고 새로운 프로토타입 객체를 만들어낸다.
Object.create 의 MDN 자료가 궁금하다면 👉🏻 read more
프로토타입 체인에 대해 더 알아보자 👉🏻 read more