자바스크립트는 객체지향 언어입니다. 하지만 C++. JAVA, PHP와 같은 언어와 다르게 클래스가 없었습니다. ES6에 class가 있지만 이는
Syntax Sugar
일뿐 내부적으로는Prototype
을 통해 상속을 흉내는 건 마찬가지입니다. 때문에 class 기반언어라고 부르지 못하고 자바스크립트를 프로토타입 기반언어라고 부릅니다.
프로토타입이란 무엇이고 자바스크립트는 어떤 방식으로 상속을 하는지 자바스크립트 내부 동작 원리에 대해서 알아보자.
자바스크립트에는 Prototype Link
와 Prototype Object
라는 것이 존재한다. 그리고 이 둘을 Prototype
이라고 부른다.
자바스크립트는 객체지향 언어이고,
객체는 언제나 함수(Function)로 생성된다.
function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성
personObject 객체는 Person이라는 함수로 생성된 객체이다. 이렇듯 언제나 객체는 함수에서 시작된다.
var obj = {};
위 코드는 다음 코드와 같다.
var obj = new Object();
위 코드에서 Object
가 자바스크립트에서 기본적으로 제공하는 함수
이다.
Object도 함수다!
Object와 마찬가지로 Function, Array도 모두 함수로 정의되어 있다.
그렇다면 이것이 Prototype Object랑 무슨 상관이 있을까? 함수가 정의될 때는 2가지 일이 동시에 이루어진다.
해당 함수에 Constructor(생성자) 자격 부여
Constructor 자격이 부여되면 new를 통해 객체를 만들어 낼 수 있게 된다. 이것이 함수만 new 키워드를 사용할 수 있는 이유이다.
constructor가 아니면 new를 사용할 수 없다!
해당 함수의 Prototype Object 생성 및 연결
함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성이 된다. 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있다. Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor
와 __proto__
를 가지고 있다.
prototype 속성으로 Prototype Object에 접근
constructor
는 Prototype Object와 같이 생성되었던 함수를 가리키고 있다.
__proto__
는 프로토타입 링크 (Prototype Link)다. 아래에서 다시 확인해보자.
아래 새로운 Car() 함수를 생성하고 console.dir()로 car.prototype과 car.prototype.constructor를 찍어보면 아래 화면과 같이 출력된다.
function Car() {
console.log('car');
}
console.dir(Car.prototype);
console.dir(Car.prototype.constructor);
constructor
와 __proto__
가 있다.결과를 그림으로 표현하면 아래와 같다.
여기서 중요한 핵심은 함수 객체와 프로토타입 객체는 서로를 바라보고 있다는 점(참조)이다.
function Car(name, wheels){
this.name = name;
this.wheels = wheels;
}
Car.prototype.gasoline = function(x){return x + '리터 만큼 충전완료'}
//car 객체 생성
var benz = new Car('banz', 4);
var audi = new Car('audi', 4);
객체를 생성하면 아래 그림과 같이 Car() 생성자 함수와 프로토타입 객체도 함께 생성된다.
또한 new 키워드를 이용해 var benz = new Car('banz', 4);
와 var audi = new Car('audi', 4);
benz 객체와 audi 객체를 생성한다.
여기서 두 new 객체 또한 프로토타입 객체(Prototype Object)를 참조한다.
이를 총 정리한 그림은 아래와 같다.
여기서 __proto__
는 프로토타입 링크 (Prototype Link)이며 프로토타입 객체를 연결한다.
console.log(benz.gasoline(1));
과 console.log(audi.gasoline(2));
를 찍어보면 어떻게 될까?
console.log(benz.gasoline(1));
//1리터 만큼 충전완료
console.log(audi.gasoline(2));
//2리터 만큼 충전완료
두 객체에 gasoline()이 정의되어 있지 않지만 참조되어있는 프로토타입 객체의 gasoline()이 있기 때문에 gasoline을 참조 할 수 있다.
이를 프로토타입 체이닝(prototype chaining)이라고 한다.
__proto__
혹은 프로토타입 링크 (Prototype Link)라고 불리는 녀석을 타고 부모 역할을 하는 프로토타입 객체를 스캔한다.이런 과정을 통해 자바스크립트는 상속기능을 흉내내 사용할 수 있다.
__proto__
속성은 모든 객체들이 가지고 있다.__proto__
속성은 자신의 부모 역할을 하는 상위 프로토타입을 가리킨다.인사이드 자바스크립트
[Javascript ] 프로토타입 이해하기_오승환님의 블로그
[JS Core]JavaScript 프로토타입 체이닝(Prototype Link, Prototype Object)