[JS] 프로토타입의 개념

cabbage·2023년 6월 15일

JS

목록 보기
36/43
post-thumbnail

기술면접을 준비하는 과정에서 자바스크립트의 프로토타입 개념에 대해 공부하였고 프로토타입 개념에 대해 정리한다. 이 정리글은 코어 자바스크립트(정재남)를 참고하여 작성하였다.

프로토타입

자바스크립트는 프로토타입 기반 언어로, 어떤 객체를 프로토타입으로 삼고 이를 참조함으로써 상속과 비슷한 효과를 얻는다.

  • 많은 프로그래밍 언어들은 클래스 기반 언어이지만 자바스크립트는 프로토타입 기반 언어라는 점이 독특하다.
var instance = new Constructor();

이 코드는 다음과 같이 이해할 수 있다.

  • 어떤 생성자 함수 Constructor를 new 연산자와 함께 호출한다.
  • Constructor에 정의된 내용을 바탕으로 새로운 인스턴스(instance)가 생성된다.
  • 이때 instance에는 __proto__ 라는 프로퍼티가 자동으로 부여된다.
  • __proto__ 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조한다.

prototype 프로퍼티와 __proto__ 프로퍼티의 관계가 프로토타입 개념의 핵심이다.

  • prototype 프로퍼티는 객체이고, 이를 참조하는 __proto__ 프로퍼티 역시 객체이다.
  • prototype 내부에는 인스턴스가 사용할 메서드를 저장한다.
  • 인스턴스에서 __proto__ 프로퍼티를 통해 prototype 내부에 저장된 메서드에 접근할 수 있다.
var Person = function (name) {
	this._name = name;
};

Person.prototype.getName = function() {
	return this._name;
};

Person 생성자 함수의 prototype 프로퍼티에 getName 메서드를 추가하였다. 이제 Person의 인스턴스는 __proto__ 프로퍼티를 통해 getName 메서드를 호출할 수 있다.

var cabbage = new Person('cabbage');
console.log(cabbage.__proto__.getName()); // undefined

'cabbage'가 아닌 'undefined'가 출력되었다. 이것은 자바스크립트의 this 바인딩 때문이다. 어떤 함수를 메서드로서 호출하는 경우 메서드 바로 앞의 객체가 곧 this가 된다.

  • 이 경우 cabbage 인스턴스가 this가 되지 않고 cabbage.__proto__가 된다.
  • __proto__도 객체이고 이 객체 내부에는 name 프로퍼티가 존재하지 않으므로 undefined가 반환된다.

따라서 this를 인스턴스로 하려면 __proto__ 없이 인스턴스에서 곧바로 메서드를 사용한다.

var cabbage = new Person('cabbage');
console.log(cabbage.getName()); // cabbage
  • __proto__를 생략하면 this는 인스턴스인 cabbage가 된다.

이 코드가 동작하는 이유는 __proto__ 프로퍼티는 생략 가능하기 때문이다.

  • __proto__를 생략하면 this는 인스턴스를 가리킨다.
  • __proto__를 생략하지 않으면 this는 인스턴스.__proto__를 가리킨다.
  • 인스턴스.__proto__에 있는 getName 메서드를 실행하지만 this는 인스턴스를 가리키게 되었다.

프로토타입 개념 정리

  • new 연산자로 Constructor를 호출하면 instance가 생성된다.
  • instance에는 생략 가능한 프로퍼티인 __proto__가 자동으로 부여되고, __proto__는 Constructor의 prototype 프로퍼티를 참조한다.
  • __proto__는 생략 가능하도록 구현되어 있다. 따라서 인스턴스는 Constructor의 prototype에 있는 메서드나 프로퍼티를 자신의 것처럼 사용할 수 있다.

배열과 생성자 함수 Array 예시

생성자 함수 Array와 인스턴스를 통해 생성자 함수의 prototype 프로퍼티와 인스턴스의 __proto__ 프로퍼티의 관계를 살펴보자.

var arr = [1, 2];
console.dir(arr); // 브라우저 콘솔창에서 확인하기
console.dir(Array); // 브라우저 콘솔창에서 확인하기

  • arr의 __proto__ 프로퍼티([[Prototype]])는 Array 생성자 함수의 prototype 프로퍼티를 참조한다.
  • __proto__ 프로퍼티는 생략 가능하게 설계되어 있으므로 인스턴스가 마치 자신의 메서드인 것처럼 Array.prototype의 메서드들을 사용할 수 있다.
  • Array 생성자 함수 자체의 스태틱 메서드들(from, isArray)은 인스턴스가 직접 호출할 수 없다.

정리

MDN에서 배열 메서드들을 보면 항상 Array.prototype이라는 것이 붙어 있었는데, 이게 왜 붙어 있는지 그 이유에 대해 알 수 있었다.

배열 인스턴스는 배열 메서드를 자신의 메서드처럼 사용하지만 결국 생성자 함수 Array의 prototype 프로퍼티에 있는 메서드들을 사용하는 것이다.

참고

  • 코어 자바스크립트 - 정재남
profile
캐비지 개발 블로그입니다. :)

0개의 댓글