본문 바로가기

프로그래밍/JavaScript(JS)

자바스크립트(JavaScript) - 프로토타입(Prototype)

글에 오류가 있을 수도 있으니 알려주시면 감사하겠습니다.

 

프로토타입(prototype) 객체

자바스크립트에서 프로토타입 객체는 중요한 객체라고 할 수 있습니다. 자바스크립트는 프로토타입 기반 언어이기 때문입니다. 프로토타입 객체를 통해 메소드와 속성을 상속받을 수 있습니다. ES6에서는 좀 더 쉽게 상속을 할 수 있는 클래스가 있습니다.

 

자바스크립트의 프로토타입 객체는 다른 객체에 프로퍼티를 공유하는 객체입니다. 함수 객체에는 prototype 프로퍼티와 [[Prototype]] 프로퍼티를 가지고 있습니다. 일반 객체에는 [[Prototype]] 프로퍼티만 가지고 있습니다. 

 

[[Prototype]]은 자바스크립트의 내부 슬릇이라는 내부 프로퍼티이며 직접적으로 접근이 불가능합니다. 하지만 요즘 브라우저에서 __proto__ 프로퍼티로 접근이 가능합니다. ES6부터는 Object.getPrototypeOf() 메소드를 통해서도 가져올 수 있습니다.

 

함수 객체에있는 prototype 객체는 함수의 prototype 객체를 참조하고 있고 prototype 객체의 constructor 프로퍼티는 함수를 참조하고 있습니다. 즉 서로를 참조하고 있습니다.

 

prototype 객체도 객체이므로 마찬가지로 [[Prototype]] 프로토타입과 __proto__ 프로퍼티를 가지고있습니다.

 

이 생성자 함수에 있는 프로토타입 객체는 생성자 함수를 통해 새로 만들어지는 인스턴스 객체에 __proto__ 프로퍼티에서 참조합니다.

function a() { 
    name : "A"
};

var b = new a();

console.log(a.prototype); 
// -> 
/*
{constructor: ƒ}
constructor: ƒ a() { \n            this.name = "A"\n        }
[[Prototype]]: Object
__proto__ (get): ƒ __proto__()
__proto__ (set): ƒ __proto__()
*/

console.log(a.prototype == b.__proto__); // -> true
console.log(b.__proto__);
/*
// ->
{constructor: ƒ}
constructor:ƒ a() { \n            this.name = "A"\n        }
[[Prototype]]:Object
__proto__ (get):ƒ __proto__()
__proto__ (set):ƒ __proto__()
*/

코드와 결과를 보면 a의 인스턴스 b의 __proto__ 프로퍼티는 a의 프로토타입 객체를 참조하고 있습니다.

계속 해서 프로토타입을 거슬로 올라가면 최종적으로 Object를 가르킵니다.

프로토타입을 쓰는 이유는?

프로토타입을 쓰는 이유는 기존 생성자 함수에 메소드를 정의하여 인스턴스에서 사용하였습니다.

function a(name) { 
    this.name = name;
    this.ab = function () {
    	console.log(this.name);
    };
};

var b = new a("AAA");
b.ab(); // -> "AAA"

var c = new a("BBB");
c.ab(); // -> "BBB"

이렇게 같은 메소드를 계속해서 사용하고 있습니다. 객체를 만들때 마다 같은 메소드를 계속해서 생성하여 메모리가 낭비가 됩니다. 따라서 이 프로토타입 객체에 메소드를 추가하여서 메모리를 줄일수 있습니다. 

function a(name) { 
    this.name = name;
};

a.prototype.ab = function () {
    console.log(this.name);
};

var b = new a("AAA");
b.ab(); // -> "AAA"

var c = new a("BBB");
c.ab(); // -> "BBB"

 

프로토타입 체인

위에서 설명한 코드에서 프로토타입 체인은 생성된 객체로 정의하지 않은 메소드를 호출했을때 프로토타입을 참조하여 프로토타입 객체에 해당 메소드가 있는지 확인하여 호출합니다. 계속 해서 없다면 같은 방법으로 프로토타입을 확인하여 메소드를 찾습니다. Object의 프로토타입까지 갔지만 없다면 메소드를 찾을수 없다고 에러가 나타납니다.

 

참고

모던 자바스크립트 입문(이소 히로시 지음, 서재원 옮김)

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Object_prototypes#create()_%EB%8B%A4%EC%8B%9C%EB%B3%B4%EA%B8%B0