[JS] 프로토타입 이해하기 with 프로토타입 체인
여의도한량이
1
12001
0
0
2021.04.26 17:32
https://www.debuggr.io/js-prototype-in-depth/
http://polyglot-m.blogspot.com/2015/12/ecma6-babeljs-webpack-es6-using-react.html
자바스크립트는 Java, Python 처럼 객체지향언어(Object-Oriented Programming, OOP)입니다.
객체지향이란 프로그램을 그저 데이터와 처리방법으로 나누는게 아니고, 프로그램을 다수의 "객체"로 만들고, 이들이 서로 상호작용을 통해 만들어지는 방식입니다. 예를 들어 자동차가 있다고 하면 자동차의 바퀴, 엔진, 도어 등을 객체라고 할 수 있습니다. 이 글은 프로토타입에 관한 글 이므로 객체 지향에 대해선 이 정도만 알고 가겠습니다.
하지만 클래스가 존재하는 Java와는 달리 자바스크립트(이하 JS)에는 클래스라는 개념이 없습니다. 대신 JS에는 프로토타입이라는 개념이 존재합니다. 이 때문에 JS가 프로토타입 기반의 객체지향 언어라고 불리는 이유입니다.
ECMA6에서 클래스 문법이 추가되었지만 이것이 JS가 Java처럼 클래스 기반의 언어로 바뀌는 것은 아닙니다. 그저 사용만 할 수 있는 것이지요.
그럼 프로토타입은 무엇이고 어디에 사용할까요?
JS는 함수와 new(생성자)를 이용하여 클래스 마냥 비스무리하게 구현할 수는 있습니다.
functionZoo(){//=> 함수this.lion = 2;
this.tiger = 3;
}
var zooKeeper_A = new Zoo(); //=> 객체var zooKeeper_B = new Zoo(); //=> 객체console.log(zooKeeper_A.lion); //=> 2console.log(zooKeeper_A.tiger); //=> 3console.log(zooKeeper_B.lion); //=> 2console.log(zooKeeper_B.tiger);//=> 3
A 사육사와 B 사육사는 lion과 tiger을 각 2개씩 가지고 있습니다. 그리고 메모리에는 lion과 tiger가 총 4개 할당됩니다. 만약 1000개의 객체가 있다면 메모리에는 총 2000개가 할당될 것이고, 이것은 상당한 메모리 낭비를 초래합니다. 이러한 이유 때문에 프로토타입을 사용해야합니다.
혹시 this.tiger = 3 라서 2개, 3개씩 가지고 있지 않느냐 생각하실수도 있겠지만 여기선 각 2개씩 가진다는건 속성의 갯수를 말하는 겁니다. lion 속성과 tiger라는 속성 총 2개를 가지고 있는 것이지요.
functionZoo(){}
Zoo.prototype.lion = 2; //프로토타입 속성인 lion
Zoo.prototype.tiger = 3; //프로토타입 속성인 tigervar zookeeper_A = new Zoo();
var zookeeper_B = new Zoo();
console.log(zooKeeper_A.lion); //=> 2console.log(zooKeeper_A.tiger); //=> 3console.log(zooKeeper_B.lion); //=> 2console.log(zooKeeper_B.tiger); //=> 3
위 코드는 프로토타입을 사용하여 구현한 코드입니다.
Zoo.prototype 이라는 prototype Object 가 메모리 어딘가에 존재하고 있을 것이고, Zoo 함수로 생성된 사육사A, 사육사B 객체들은 메모리 어딘가에 있을 prototype Object 를 사용할 수 있게 됩니다.
(prototype Object에 관해서는 아래에서 설명합니다.)
즉, 메모리 어딘가에 존재할 prototype의 lion, tiger 속성을 사육사A, 사육사B가 공유하여 사용할 수 있게 됩니다.
prototype Link 와 prototype Object
prototype Link 와 Prototype Object, 이 둘을 통틀어 prototype이라고 합니다.
prototype object
객체는 언제나 함수로부터 생성됩니다.
functionZoo(){}
var zooObj = new Zoo(); //=> zooObj는 객체, Zoo()는 함수
이렇듯 객체는 언제나 함수로부터 생성됩니다. 우리가 흔히 사용하는 일반적인 객체 생성도 마찬가지입니다.
var zooObj = {}//=> 객체 생성 방법
위처럼 객체를 생성하는 방법은 사실 다음과도 같습니다.
var zooObj = newObject();//=> 이렇게도 객체 생성이 가능함
위 코드에서 Object()가 JS에서 제공하는 기본함수입니다.
객체를 생성시켜주는 Object 또한 함수입니다.객체도 결국 함수로부터 생성됩니다.
그럼 이것이 protype Object 랑 무슨 상관이 있느냐?
함수가 정의될 때 다음과 같은 2가지 일이 일어납니다.
1. 해당 함수에 Constructor(생성자) 자격 부여
Constructor 자격이 부여되야 new(생성자)를 통해 객체를 생성할 수 있습니다. 이것이 함수만이 new 키워드를 사용할 수 있는 이유입니다.
2. 해당 함수의 prototype Object 생성 및 연결
함수가 생성될 때 생성된 함수는 prototype 이라는 속성을 가지게 됩니다. 이 prototype이라는 속성은 prototype Object 라는 객체에 접근을 가능하게 해줍니다. 또 prototype Object는 일반적인 객체와 같으며, 기본속성으로 constructor, __proto__를 가집니다.
function Zoo의 속성인 prototype은 Zoo prototype Object를 가르키고 Zoo prototype Object의 속성 constructor는 function Zoo를 가르킵니다.
(constructor 말고 __proto__라는 것도 생성되는 데 이것은 밑에서 설명하겠습니다.)
functionZoo(){}
Zoo.prototype.lion = 2; //프로토타입 속성인 lion
Zoo.prototype.tiger = 3; //프로토타입 속성인 tigervar zookeeper_A = new Zoo();
var zookeeper_B = new Zoo();
console.log(zooKeeper_A.lion); //=> 2console.log(zooKeeper_A.tiger); //=> 3console.log(zooKeeper_B.lion); //=> 2console.log(zooKeeper_B.tiger); //=> 3
이제 이 코드를 보고 조금 이해가 가시나요?? prototype Object는 일반 객체이므로 마음대로 속성 추가/삭제가 가능합니다. 또 사육사 A와 사육사 B는 Zoo 라는 함수를 통해 생성되었으니 Zoo.prototype 을 참조할 수 있습니다. 따라서 위 코드와 같이 출력할 수 있었던 겁니다.
prototype Link
사육사 A에 lion과 tiger라는 속성이 없는데 보시는 바와 같이 2와 3이 출력됩니다. new Zoo() 로 생성된 객체 사육사 A가 조상이였던 Zoo 함수의 prototype Object를 참조할 수 있었기에 위와 같은 결과를 출력할 수 있었던 것입니다. 그리고 이러한 결과를 가능케 해주는 것이 바로 prototype Link 즉, __proto__ 입니다.
prototype 속성은 함수만 가지고 있는 반면, __proto__는 모든 객체가 가지고 있는 속성입니다.
__proto__ 는 객체가 생성될 때 조상이였던 함수의 prototype Object를 가르키게 됩니다. 따라서 사육사 A는 Zoo 함수로부터 생성되었으니 Zoo 함수의 prototype Object를 가르킵니다.
사육사 A가 lion, tiger 를 직접 가지고 있지 않아 lion, tiger 속성을 찾을 때까지 상위 프로토타입을 탐색하게 됩니다. 만약 최상위 Object인 Object prototype Object 까지 도달했는 데 없다면 undefined를 출력합니다. 이렇게 __proto__ 속성을 통해 상위 프로토타입과 연결되어 있는 형태를 프로토타입 체인이라고 합니다.
이러한 프로토타입 체인 구조 덕분에 모든 객체는 Object의 자식이라고 불리고 Object prototype Object의 모든 속성을 사용할 수 있게 됩니다.
요약
1. 함수가 생성될 때 2가지 일이 발생합니다.
-
constructor 자격 부여 권한
-
해당함수의 prototype 속성과 prototype Object를 가지며 prototype Object는 constructor과 __proto__ 속성을 갖습니다.
2. prototype은 prototype Object 를 가르키고, prototype Object의 constructor 속성을 함수를 가르킵니다.
3. prototype Link 인 __proto__ 는 모든 객체가 가지는 속성이며 상위 프로토타입 간 연결을 해줍니다.
4. __proto__ 속성의 특징 덕분에 프로토타입 체인 형태를 가질수 있습니다.
5. Object prototype Object 는 모든 객체가 접근 가능합니다.(가장 최상위 프로토타입이기 때문)
읽어주셔서 감사합니다.
질문은 언제나 환영합니다.
"난 반드시 백엔드 왕이 될거야"