Judaeng
OOP(2) Javascript의 Prototype 기반 객체지향 프로그래밍 본문
지난 글에선 객체지향 언어에서 핵심이 되는 개념인 클래스(Class)에 대해 정리한 글을 작성했다.
오늘은 Javascript에 프로토타입(Prototype)이라는 개념을 정리하려고 한다.
자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다.
객체지향의 상속 개념과 같이 부모 객체의 프로퍼티를 마치 자신의 것처럼 쓸 수 있는 특징이 있다.
자바스크립트에서는 이러한 부모 객체를 프로토타입 객체라고 부른다.
클래스라는 개념이 존재하는 Class 기반 언어들은 상속을 사용한다.
Class 기반 언어들의 예를 들자면 Java, C++ 등이 있다.
하지만 Javascript는 이와 달리 Prototype 기반 언어이다.
클래스가 없기 때문에 상속 같은 기능도 따로 존재하지 않는다.
정리하자면, Prototype 기반 언어는 어떤 객체를 원형(Prototype)으로 삼고, 그 객체를 복제해 상속과 비슷한 기능을 한다.
Prototype
Javascript에는 클래스는 없지만 함수와 new 키워드를 이용해 클래스를 흉내 낼 수 있다.
함수가 정의될 때는 해당 함수에 생성자(Constructor) 자격이 부여되고, 이렇게 자격을 부여받으면 new를 통해 객체를 만들어 낼 수 있다.
객체는 항상 함수로만 생성되기 때문에 new 키워드 또한 함수만 사용할 수 있다.
function Person() {
this.eyes = 2;
this.nose = 1;
}
var kang = new Person();
var kim = new Person();
console.log(kang.eyes); // => 2
console.log(kang.nose); // => 1
console.log(kim.eyes); // => 2
console.log(kim.nose); // => 1
kang과 kim은 eyes와 nose를 공통적으로 가지고 있는데, 메모리에는 eyes와 nose가 두 개씩 총 4개씩 할당된다.
이것을 프로토타입으로 해결해보자.
function Person() {}
Person.prototype.eyes = 2;
Person.prototype.nose = 1;
var kang = new Person();
var kim = new Person();
console.log(kim.eyes); // => 2
빈 Person.prototype이라는 빈 Object가 어딘가에 존재하고, Person 함수로부터 생성된 객체(kang, kim)들은 어딘가에 존재하는 Object에 들어있는 값을 모두 갖다 쓸 수 있다.
eyes와 nose를 어딘가에 있는 빈 공간에 넣어놓고 kang과 kim이 공유해서 사용하는 것이다.
Prototype Link와 Prototype Object
자바스크립트에는 Prototype Link와 Prototype Object라는 것이 존재한다.
이 둘을 통틀어 Prototype라고 부른다.
Prototype Object
객체는 언제나 함수(Function)로 생성된다.
personObject 객체는 Person이라는 함수로 생성된 객체이고, 언제나 객체는 함수에서 시작된다.
// 1
function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성
// 2
var obj = {}; // 얼핏보면 함수랑 전혀 상관없는 코드로 보이지만 위 코드와 같다.
// 3
var obj = new Object(); // 이 코드를 콘솔창에 치게되면 Object도 함수라는 것을 알 수 있다.
// 설명
Object와 마찬가지로 Function, Array도 모두 함수로 정의되어 있다.
1. 해당 함수에 Constructor(생성자) 자격 부여
Constructor 자격이 부여되면 new를 통해 객체를 만들어 낼 수 있게 된다.
이것이 함수만 new키워드를 사용할 수 있는 이유이다.
2. 해당 함수의 Prototype Object 생성 및 연결
함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성된다.
그리고 생성된 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있다.
Prototype Object는 일반적인 객체와 같고, 기본적인 속성으로 constructor와 __proto__를 가지고 있다.
아래와 같이 콘솔 창에 입력하게 되면 저런식으로 출력하게 된다.
constructor는 Prototype Object와 같이 생성되었던 함수를 가리키고 있다.
Prototype Object는 일반적인 객체이므로 속성을 마음대로 추가/삭제할 수 있다.
kang과 kim은 Person 함수를 통해 생성되었으니 Person.prototype을 참조할 수 있게 된다.
Prototype Link
__proto__는 Prototype Link이다.
kang에는 eyes라는 속성이 없는데도 kang.eyes를 실행하면 2라는 값을 참조하는 것을 볼 수 있다.
Prototype Object에 존재하는 eyes 속성을 참조한 것이다.
kang이 가지고 있는 딱 하나의 속성 __proto__가 그것을 가능하게 해주는 방법이다.
prototype 속성은 함수만 가지고 있던 것과는 달리 __proto__속성은 모든 객체가 빠짐없이 가지고 있는 속성이다.
__proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킨다.
kang객체는 Person함수로부터 생성되었으니 Person 함수의 Prototype Object를 가리키고 있는 것이다.
__proto__의 결과를 보니 역시 Person 함수의 Prototype Object를 가리키고 있었다.
kang 객체가 eyes를 직접 가지고 있지 않기 때문에 eyes 속성을 찾을 때 까지 상위 프로토타입을 탐색한다.
최상위인 Object의 Prototype Object까지 도달했는데도 못찾았을 경우 undefined를 리턴한다.
이렇게 __proto__속성을 통해 상위 프로토타입과 연결되어 있는 형태를 포로토타입 체인(Chain)이라고 한다.
이렇게 생긴 프로토타입 체인 구조 때문에 모든 객체는 Object의 자식이라고 불리고, Object Prototype Object에 있는 모든 속성을 사용할 수 있다.
constructor 속성
속성을 하나 정리해보자.
constructor는 자기 자신, 즉 생성자 함수를 참조하는 속성이다.
instance의 원형이 되는 생성자함수가 무엇인지 알게 해주는 역할이라고 할수 있다.
let Person = function(name, age) {
this.name = name;
this.age = age;
}
judaeng = new Person('강주현', 39);
아래처럼 constructor 속성을 확인해보면, 어떤 생성자 함수가 instance를 만든 것인지 추적할 수 있다.
정리
✏️ Prototype 정리
1) Constructor(생성자함수)를 new로 호출한다.
2) Constructor 내용을 기반으로 새 instance 생성한다.
3) instance에는 __proto__라는 속성이 부여된다.
4) 이 속성은 Constructor의 prototype 속성을 참조한다.
'Develop > JavaScript' 카테고리의 다른 글
OOP(1) 객체지향 프로그래밍, 클래스 (0) | 2021.03.01 |
---|---|
상황의 따라 바뀌는 this (0) | 2021.03.01 |
비동기 호출(2) (0) | 2021.02.14 |
비동기 호출(1) (0) | 2021.02.14 |
로컬 스토리지(localStorage) json (0) | 2021.02.08 |