본문 바로가기

Frontend/Javascript

[Javascript] Prototype 프로토타입

안녕하세요.

자바스크립트에 대해 공부하다 보면, '자바스크립트는 프로토타입 기반 언어이다.'라는 말을 들어보셨을 겁니다.

오늘은 여기서 말하는 프로토타입이 무엇인지에 대해서 알아보도록 하겠습니다.

 

자바스크립트에서 사용되는 프로토타입이란 용어는 크게 두 가지로 나뉩니다.

첫 번째는 자기 자신을 만들어낸 객체의 원형을 의미하는 Prototype Link이고, 두 번째는 Prototype Property가 가리키고 있는 Prototype Object입니다.

🔸 Prototype이란? 

자바스크립트의 모든 객체는 자신을 생성한 객체 원형에 대해 연결을 갖습니다. 이때 자기 자신을 생성하기 위해 사용된 객체 원형을 프로토타입이라고 합니다. 즉, 위에서 말한 Prototype Link가 가리키고 있는 객체를 말합니다.

자바스크립트의 모든 객체는 Object 객체의 프로토타입을 기반으로 확장되었기 때문에 Prototype Link의 끝은 Object 객체의 프로토타입 Object입니다.

 

예제를 통해 확인해봅시다.

function Person(name){
    this.name = name;
};
var p = new Person('Kei');
console.log(p);

위 코드를 실행하고 console을 확인해봅시다.

 

[[Prototype]]이 p라는 객체를 만들어내기 위해 사용한 객체 원형에 대한 숨겨진 연결입니다.

p 객체의 프로토타입은 Person이라는 함수 객체이며, p 객체의 생성자는 constructor에서 보실 수 있듯이 function Person() 함수라는 것입니다.

 

Prototype Link가 생성되는 시점 

생성자 함수를 new 연산자와 함께 호출하면 객체에 [[Prototype]]이 자동적으로 부여되고, Constructor의 Prototype이라는 프로퍼티를 참조하게 됩니다.

(책이나 블로그에서는 [[Prototype]]를 __proto__로 표기하고 있습니다. __proto__ 속성은 [[Prototype]]에 접근하는 속성으로, __proto__와 [[Prototype]]을 동일한 것으로 생각하셔도 됩니다.)

🔸 Prototype Property란?

그렇다면 Prototype Property란 무엇일까요? 

Prototype Property는 자신을 통해 만들어질 객체들이 원형으로 사용할 객체를 말합니다.

 

위의 예제를 조금 변형해봅시다.

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

var p = new Person('Kei');
console.log(p);
console.log(p.getName()); //Kei

Person.prototype에 getName이라는 함수를 정의한 후, Person 함수 객체를 원형으로 하여 객체 p를 생성하였습니다.

p 객체의 [[Prototype]]을 보니, getName이라는 함수가 보입니다.

이를 통해 p객체의 [[Prototype]]이 Person의 Prototype Property를 참조하게 되어, p객체의 [[Prototype]] 속성에서 getName 함수를 볼 수 있습니다.

 

Prototype Object가 생성되는 시점

함수를 정의하기만 해도 기본적으로 Prototype Object가 생성됩니다. (함수 객체만 Prototype Property를 가집니다.) 

함수 선언문의 함수는 Prototype Obejct를 가지고 있으며, Constructor는 자기 자신으로, [[Prototype]] 속성으로는 Object를 가리키고 있습니다.

(다만, 화살표 함수는 Prototype Object를 가지고 있지 않으며, 생성자 함수로 사용할 수 없습니다.)

 

Constructor란?

생성자 함수의 prototype property 내부에 존재하는 프로퍼티로, 원래의 생성자 함수(자기 자신)를 참조합니다.

생성자 함수로 인스턴스를 생성한 후에, 그 인스턴스의 원형이 무엇인지 알고 싶을 때 사용할 수 있습니다.

var arr = [1,2];
Array.prototype.constructor === Array // true
arr.__proto__.constructor === Array // true
arr.constructor === Array // true

 

관계도

관계를 그림으로 나타내면 다음과 같습니다.

🔸 Prototype Chain

데이터의 [[Ptototype]]의 내부에 다시 [[Prototype]]이 연쇄적으로 이어진 것을 프로토타입 체인이라고 하고, 이 체인을 따라가며 검색하는 것을 프로토타입 체이닝이라고 합니다.

다시 위의 예제를 봅시다.

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

var p = new Person('Kei');
console.log(p);
console.log(p.getName()); //Kei

p.getName()을 호출하면, 먼저 p객체 안에 getName 메서드가 있는지 찾습니다. p객체 안에 getName 메서드가 존재하지 않기 때문에 [[Prototype]] 안에서 getName 메서드를 찾습니다. Person의 Prototype Object에 getName 메서드를 선언하였기 때문에 해당 메서드를 사용하게 됩니다.  

만약 최상위 객체에 도달할 때까지 해당 메소드를 찾지 못한다면 에러를 반환하게 됩니다.

 

hasOwnProperty 메소드

프로퍼티가 객체의 것인지, 프로토타입 체인의 어딘가에 있는 것인지 확인하기 위해 사용할 수 있습니다.

console.log(p.hasOwnProperty('name')); //true
console.log(p.hasOwnProperty('getName')); //false

🔸 Prototype 사용의 장점

Prototype 기반 언어의 장점은 재사용성을 높이고, 메모리를 절약할 수 있다는 점입니다.

function Person(name){
    this.name = name;
    this.age = 20;
};
Person.prototype.getName = function(){
    return this.name;
}

var p1 = new Person('Kei');
console.log(p1);

var p2 = new Person('Mark');
console.log(p2);

this로 선언한 name, age의 경우 p1, p2에 모두 생성되지만, Person의 Prototype Object에 선언한 getName 함수는 한 번만 만들어서 사용할 수 있습니다. 

 

오늘은 Prototype에 대해서 알아보았습니다.

틀린 부분이나 궁금한 것이 있으면, 댓글 부탁드립니다.

 

감사합니다.

 

출처 : http://insanehong.kr/post/javascript-prototype/

        https://mygumi.tistory.com/312

        https://velog.io/@turtle601/Prototype%EC%9D%B4%EB%9E%80

        책 코어 자바스크립트

 

  

'Frontend > Javascript' 카테고리의 다른 글

[Javascript] Generator  (0) 2022.06.12
[Javascript] Promise  (0) 2022.04.04
[Javascript] Garbage Collection  (0) 2022.03.22
[Javascript] Closure 클로저  (0) 2022.03.17
[Javascript] this  (0) 2022.03.09