[JS]프로토타입 이해하기

KBS·2022년 1월 12일
0

JS

목록 보기
6/9


기술면접을 보게 되었는데, 프로토타입에 대해 제대로 설명하지 못하였다...
이를 보완하고자 정리하려고 한다!
한 블로그를 참조했는데, 매우 잘 설명되어 있어 참조하였다.
https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

자바스크립트는 프로토타입 기반 언어라고 불린다.

Prototype vs Class

클래스(Class)는 객체지향 언어에서 빠질 수 없는 개념이다.
자바스크립트 또한 객체지향 언어이다. 하지만 자바스크립트에는 클래스 라는 개념이 없다. 대신 Prototype이 존재한다.

클래스가 없으니 기본적으로 상속 기능도 없다. 이를 보완하고자 프로토타입 기반으로 상속을 흉내내도록 구현해 사용한다.
(최근 ECMA6 표준에서는 Class 문법이 추가되었다.)

Prototype 구현

자바스크립트에 클래스는 없지만 함수(function)와 new를 통해 클래스를 비슷하게 흉내낼 수 있다.

function Person() {
	this.eyes = 2;
    this.nose = 1;
}

let kim = new Person();
let park = new Person();

console.log(kim.eyes); // =>2
console.log(kim.nose); // =>1

console.log(park.eyes); // =>2
console.log(park.nose); // =>1

kim과 park은 eyes와 nose를 공통적으로 가지고 있는데, 메모리에는 eyes와 nose가 두개씩 총 4개 할당된다. 객체를 100개 만들면 200개의 변수가 메모리에 할당될 것이다.
이러한 문제를 프로토타입으로 해결할 수 있다.

function Person() {}

Person.prototype.eyes = 2;
Person.prototype.nose = 1;

let kim = new Person();
let park = new Person();

console.log(kim.eyes); // =>2

Person.prototype이라는 빈 Object가 어딘가에 존재하고, Person 함수로부터 생성된 객체(kim, park)들은 어딘가에 존재하는 Object에 들어있는 값을 모두 갖다 쓸 수 있다.
즉, eyes와 nose를 어딘가에 빈 공간에 넣어놓고 kim과 park이 공유해서 사용하는 것이다.

프로토타입은 깊게 팔수록 복잡하지만 사용되는 부분은 이것이 거의 전부라고 한다. 개발자는 항상 사용법만 알고 있는것이 아니라 왜? 라는 질문을 가져야 한다.

자바스크립트에는 Prototype Link와 Prototype Object라는 것이 존재한다. 이 둘을 통틀어 Prototype이라고 부른다.

Prototype Object

객체는 언제나 함수(Function)로 생성된다.

function Person() {} // => 함수
let personObject = new Person(); // => 함수로 객체를 생성

personObject 객체는 Person이라는 함수로 생성된 객체이다. 이렇듯 언제나 객체는 함수에서 시작된다. 일반적으로 쓰이는 일반적인 객체 생성도 마찬가지 이다.

let obj = {};

얼핏보면 함수랑 전혀 상관없는 코드로 보이지만 위 코드는 다음 코드와 같다.

let obj = new Object();

위 코드에서 Object가 자바스크립트에서 기본적으로 제공하는 함수이다.

Object와 마찬가지로 Function, Array도 모두 함수로 정의되어 있다.

그렇다면 이것이 Prototype Object랑 무슨 상관이 있느냐 하면.
함수가 정의될 때는 2가지 일이 동시에 이루어진다.

1. 해당 함수에 Constructor(생성자) 자격 부여

Constructor 자격이 부여되면 new를 통해 객체를 만들어 낼 수 있게 된다. 이것이 함수만 new 키워드를 사용할 수 있는 이유이다.

2. 해당 함수의 Prototype Object 생성 및 연결

함수를 정의하면 함수만 생성되는 것이 아니라 prototype Object도 같이 생성된다.

함수를 정의하면 이렇게 된다.

그리고 생성된 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있다. Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor와 __proto__를 가지고 있다.

constructor는 Prototype Object와 같이 생성되었던 함수를 가리키고 있다.
__proto__는 Prototype Link이다. (추후 상세설명)

아까 위에서 보았던 kim과 park이 나왔던 예제를 다시 보면

function Person() {}

Person.prototype.eyes = 2;
Person.prototype.nose = 1;

var kim  = new Person();
var park = new Person():

console.log(kim.eyes); // => 2

이제 왜 Person.prototype을 사용하는지 눈에 익을것이다.

Prototype Object는 일반적인 객체이므로 속성을 마음대로 추가/삭제 할 수 있다. kim과 park은 Person 함수를 통해 생성되었으니 Person.prototype을 참조할 수 있게 된다.

Prototype Link를 보기 전에 Prototype Object를 어느정도 이해하고 보기를 권한다. 함수가 정의될 때 이루어지는 일들을 이해하는 것이 두 번 째 포인트,Prototype Object를 이해하는 것이 세번째 포인트이다.

kim에는 eyes라는 속성이 없는데도 kim.eyes를 실행하면 2라는 값을 참조하는 것을 볼 수 있다. 위에서 설명했듯 Prototype Object에 존재하는 eyes 속성을 참조한 것인데, 이는 어떻게 가능한걸까?

바로 kim이 가지고 있는 딱 하나의 속성 __proto__가 그것을 가능하게 해주는 열쇠이다.

prototype 속성은 함수만 가지고 있던 것과는 달리 __proto__속성은 모든 객체가 빠짐없이 가지고 있는 속성이다.

__proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킨다. kim객체는 Person함수로부터 생성되었으니 Person 함수의 Prototype Object를 가리키고 있는 것이다.

__proto__를 까보면 역시 Person 함수의 Prototype Object를 가리키고 있다.

객체,함수,Prototype Object의 관계

kim 객체가 eyes를 직접 가지고 있지 않기 때문에 eyes속성을 찾을때 까지 상위 프로토타입을 탐색한다. 최상위인 Object의 Prototype Object까지 도달했는데도 못찾을 경우 undefined를 리턴한다. 이렇게 __proto__속성을 통해 상위 프로토 타입과 연결되어 있는 형태를 프로토타입 체인(Chain)이라고 한다.


프로토타입 체인, 최상위는 Object

이런 프로토타입 체인 구조 때문에 모든 객체는 Object의 자식이라고 불리고, Object Prototype Object에 있는 모든 속성을 사용할 수 있다.
한 가지 예를 들면 toString함수가 있다.

Object속성인 toString함수를 kim도 사용 가능

__proto__와 프로토타입 체인을 이해하는 것이 네번째 포인트 이다.

예시

function 기계(이름){
	this.name = 이름;
    this.age = 15;
    this.sayHi = function() {
    	console.log('안녕하세요' + this.name + '입니다')
    }
}

기계.prototype.gender = '남';

let 학생1 = new 기계('Kim');
let 학생2 = new 기계('Park');

prototype은 유전자 이다.
prototype에 값을 추가하면 모든 자식들이 물려받아 사용할 수 있다.
ex ) 학생1.gender 를 콘솔로 찍으면 '남'이 출력된다.

profile
FE DEVELOPER

0개의 댓글