1. prototype의 개념
constructor라는 생성자 함수가 있을 때
new 연산자를 써서 instance를 만들면
생성자 함수의 prototype이라는 프로퍼티가
instance의 __proto__라는 프로퍼티에 전달된다.
(전달된다는 건 __proto__를 prototype처럼 쓸 수 있다는 거겠지?)
즉, 생성자 함수의 prototype,
instance의 __proto__는 같은 객체를 참조한다.
그런데 __proto__는 생략할 수 있어서
마치 instance에 연결된 것처럼 동작할 수 있다.
(실제는 아니고, 이해를 돕기 위함)
이해를 돕기 위한 실제 데이터값으로 예시를 들면
Array생성자를 통해 [1,2,3]이라는 인스턴스를 만들었다.
Array라는 생성자를 보면 여러가지 메서드, 프로퍼티들이 존재한다.
이는 console.dir(Array)를 통해서도 확인이 가능하다.
생략이 가능하다 하니 [1,2,3]을 가리키는 셈이다.
그리고 이 중에 prototype이라는 프로퍼티가 __proto__에 연결되어 있는데,
prototype은 객체라서 여러 메서드를 사용할 수 있다.
이 이미지를 도식화한 것이 2번의 그림이다.
console.log([1,2,3]);
(3) [1, 2, 3]
0: 1
1: 2
2: 3
length: 3
__proto__: Array(0)
concat: ƒ concat()
constructor: ƒ Array()
copyWithin: ƒ copyWithin()
entries: ƒ entries()
every: ƒ every()
......
[1,2,3]을 찍어보면 __proto__가 함께 들어있는데,
__proto__를 열어보면 위 prototype처럼 메서드가 나온다.
function Person(n, a) {
this.name = n;
this.age = a;
}
var me = new Person('김율프', 6);
이런 코드가 있을때, new Person~은 Person의 instance이다.
var meClone1 = new me.__proto__.constructor('김율프_클론1', 10);
var meClone2 = new me.constructor('김율프_클론2', 15);
var meProto = Object.getPrototypeOf(me);
var meClone3 = new meProto.constructor('김율프_클론3', 20);
var meClone4 = new Person.prototype.constructor('김율프_클론4', 25);
// 답은 모두 Person {name: "김율프_클론x", age: x} 이다.
즉,
[CONSTRUCTOR].prototype
[instance].__proto__
[instance]
object.getPrototypeOf([instance])
=> 이 네가지 방식에 의해 생성자함수의 프로토타입에 접근이 가능
[CONSTRUCTOR]
[CONSTRUCTOR].prototype.constructor
(Object.getPrototypeOf([instance])).constructor
[instance].__proto__.constructor
[instance].constructor
=> 이 다섯가지 방식에 의해 생성자함수에 접근이 가능 (자기자신)
앞에서 constructor를 붙이면 된다.
이 그림과 대비해 보면서 다시 또 보고 또 보자.
이 그림과 대비해 보면서 다시 또 보고 또 보자.
2. prototype의 사용 방법
function Person(n, a) {
this.name = n;
this.age = a;
}
var me = new Person('김율프', 6);
var you = new Person('김세석', 20);
me.setOlder = function() { // me의 age를 1살씩 올리도록 세팅
this.age += 1;
}
me.getAge = function() { // me의 세팅한 나이를 가져옴
return this.age;
}
you.setOlder = function() { // you의 age를 1살씩 올리도록 세팅
this.age += 1;
}
you.getAge = function() { // you의 세팅한 나이를 가져옴
return this.age;
}
이 코드에서 현재 me와 you의 setOlder, getAge가 겹치게 된다.
function Person(n, a) {
this.name = n;
this.age = a;
}
Person.prototype.seOlder = function() { // me와 you의 age를 1살씩 올리도록 세팅
this.age += 1;
}
Person.prototype.getAge = function() { // me와 you의의 세팅한 나이를 가져옴
return this.age;
}
var me = new Person('김율프', 6);
var you = new Person('김세석', 20);
person의 instance들은 전부 자신의 것처럼 setOlder, getAge를 사용할 수 있다.
즉, 위 그림에서 constructor 부분을 건드는 게 아니라
그 옆의 prototype을 건드는 것이다.
3. prototype 체이닝
그림에 대해 설명해보면,
앞서 설명한 것처럼 Array는 생성자함수이고
그 함수를 사용하여 [1,2,3]이라는 인스턴스를 만들어냈다.
그러면 Array.prototype이라는 또 다른 프로퍼티가 생성되고
이 프로퍼티는 __proto__를 가리키지만 생략이 가능해서
마치 자신의 것처럼 [1,2,3]을 사용할 수 있다.
그런데, Array.prototype은 객체이다.
객체라는 건 Object 생성자에서 생성된 인스턴스라고 볼 수 있고,
따라서 Object.prototype을 상속받아서 Array.prototype을 사용할 수 있게 된다.
배열 [1,2,3]은 Object.prototype에서도 자신의 것인냥 사용할 수 있다.
빨간색 선을 따라서 사용할 수 있는 것을 프로토타입 체이닝이라고 부른다.
그러니까 인스턴스에서 없는 것을 타고 올라가서 prototype에서 찾을 수도 있고,
prototype에서 없는 것을 Object쪽의 prototype에서 찾을 수도 있다.
다음으로 이 프로토타입 체이닝을 통해 클래스를 사용하는 방법을 올리겠다.
-정재남님의 자바스크립트 핵심 개념강의를 이해후 재정리한 것
'프로그래밍 > JavaScript' 카테고리의 다른 글
[JavaScript] push와 concat의 중요한 차이 (0) | 2021.01.31 |
---|---|
[JS] 변수 선언 : var / let / const의 차이점[ES6] (0) | 2021.01.15 |
자바스크립트 핵심 개념 : 클로저 (0) | 2020.12.20 |
자바스크립트 핵심 개념 : 함수와 변수 사용 (0) | 2020.12.20 |
자바스크립트 핵심 개념 : this, 이것만 알면 끝 (0) | 2020.12.18 |