heeji.dev

프로토타입과 클래스

2023-11-15

프로토타입의 정의

  • 자바스크립트는 프로토타입 기반 언어이다. 프로토타입 객체를 통해 객체의 메서드와 속성들을 상속한다.
  • 자바스크립트에서는 객체를 생성할 때 자신의 부모 객체와 연결되는 링크를 가지게 된다.

프로토타입의 이해

프로토타입을 알아보기 위해 간단한 Person 생성자를 만들어보겠습니다.
1의 결과
notion image
2의 결과
notion image
생성된 person1 인스턴스를 보면 name, age, sayHi가 우리가 정의한대로 생성된 것을 볼 수 있습니다. new 키워드를 생성자 함수 앞에 붙여 인스턴스를 생성하고 (이 때 this는 인스턴스가 된다) 그곳에 속성과 메서드들을 넣어준 것입니다.
콘솔에 찍힌 prototype과 [[Prototype]]이 눈에 띕니다. 콘솔에서 아무리해도 person1의 [[Prototype]]에 접근할 수가 없네요. 검색해봅니다. [[Prototype]]의 getter이자 setter인 __proto__라는 것이 존재함을 찾을 수 있었습니다.
실행 결과
notion image
콘솔에 찍어보면 생성자 함수의 prototype과 인스턴스의 __proto__가 동일한 값임을 알 수 있습니다.
생성자 함수로 인스턴스를 생성하면 생성자함수의 prototype이 인스턴스의 [[Prototype]]으로 추가됩니다.
prototype 객체가 있고 이것이 인스턴스의 프로토타입이 된다는 것을 확인했습니다. 좀 더 알아보기 위해 sayHi 함수를 Person의 prototype에 바로 적용해볼까요
notion image
Person의 prototype과 person1의 __proto__는 동일한 객체임을 확인할 수 있습니다.
새로운 인스턴스를 생성하기 전에 prototype에 메서드를 추가했기 때문에 가능한 걸까요?
한 번 순서를 바꿔보겠습니다.
notion image
  • 인스턴스 생성 이후에 Person의 prototype에 sayHi 메서드를 정의해도 무사히 sayHi를 사용할 수 있음을 확인했습니다. 이를 통해 우리는__proto__는 prototype을 참조하는 값임을 알 수 있습니다. 생성자를 변경했음에도 그 내용이 인스턴스에 반영되니까요
이 것을 통해 우리는 응용법을 생각할 수 있습니다. 앞의 예제를 다시 봅시다.
해당 생성자로 인스턴스를 만들면
notion image
인스턴스마다 sayHi 함수가 객체의 프로퍼티로 존재하는 것을 확인할 수 있습니다. 이렇게 되면 인스턴스가 많아질 때 불필요하게 메모리를 사용하게 되는 문제가 생기겠죠. 앞에서 sayHi 메서드를 생성자의 prototype에 정의하고 사용하는 예제를 봤습니다. 이렇게 하면 인스턴스 객체의 프로퍼티에 메서드가 정의되는 것이 아니라 프로토타입을 참조해 해당 메서드를 호출할 수 있습니다.
notion image
콘솔을 보면 각 인스턴스에 sayHi 프로퍼티가 없는 것을 확인할 수 있습니다. 이렇게 되면 메모리를 아낄 수 있겠네요.
그런데 이상합니다. person1에 sayHi라는 프로퍼티가 없는데 어떻게 person1.sayHi()를 호출할 수 있는 걸까요? 이는 프로토타입 체이닝 덕분입니다.
자바스크립트는 person1.sayHi() 구문을 보고 먼저 person1이 해당 프로퍼티를 가지고 있는지 확인합니다. 만약 없다면 person1의 __proto__에서 해당 프로퍼티를 찾습니다. 이곳에서 찾으면 그것을 사용하게 됩니다. 만약 이곳에 또 없다면 __proto__의 __proto__를 찾아봅니다. 이런 식으로 프로토타입이 줄줄이 엮여있는 것을 프로토타입 체인이라고 하고 속성을 찾아다니는 것을 프로토타입 체이닝이라고 합니다. __proto__가 null이 될 때까지 프로토타입 체이닝이 일어납니다.

클래스

앞에서 메모리 효율을 위해 메서드를 prototype에 정의해보았는데요. ES6에 추가된 클래스는 이것을 사용하기 쉽게 해줍니다.
notion image
person1의 프로퍼티에 sayHi가 추가되는 것이 아니라 프로토타입에 sayHi가 정의되어있는 것을 확인할 수 있습니다.

참고자료