프로토타입이란?
- JS는 내부적으로 프로토타입 기반으로 돌아간다고 해도 무방함(즉, 프로토타입 기반 언어임)
__proto__
로 접근시, 프로토타입과 관련하여 많은 것을 볼 수 있음(각 타입에서 접근해서 확인할 수 있음)
- 어떤 값을 만들어도 내부적으로 프로토타입을 가지고 있고, 그래서 프로토타입 기반 언어라고 볼 수 있는것
constructor
- 생성자의 경우, 앞서 본 생성자 함수, 클래스 내의 생성자 함수 등 다양하게 있음
- 생성자도 모든 JS 내부에 확인이 됨(마치 프로토타입처럼)
- 아래의 예시에서 서로 다른 객체여도 동일하게 생성자 함수를 가르키는 것을 알 수 있음
function Person(name, age) {
this.name = name;
this.age = age;
}
const kevin = new Person('kevin', 99);
const hart = new Person('hart', 11);
kevin.constructor.name;
hart.constructor.name;
- 아래와 같이 각각의 타입에 있어서도 만들어진 타입에 맞는 생성자의 이름을 가지고 있음
const obj = {};
const arr = [];
const func = function () {};
const str = 'str'
obj.constructor.name
arr.constructor.name
func.constructor.name
str.constructor.name
obj instanceof Object;
arr instanceOf Array;
func instanceOf Function;
- 그래서 JS가 프로토타입 기반언어라고 볼 수 있음, 내가 만든 값들이 내부적으로 프로토타입을 다 가지고 있고, 이 프로토타입을 통해서 어떤 생성자를 통해서 만들었는지 알 수도 있음
instanceof
함수 역시 이러한 생성자를 통해서 확인하는 것(constructor로 확인한 것, 위와 같이), 그래서 instanceof 사용을 잘하면 인스턴스 타입을 확인하는데 쉬움(Primitive의 경우 래퍼 객체를 사용할 때)
- 이러한 프로토타입에 직접 접근하거나 생성자를 활용할 때, 어디서 파생됐는지 확인하는 경우 instanceof나 생성자 함수를 다 가지고 있기 때문에
.
통해 접근해서 확인할 수도 있음
proto
- 던더 프로토라고 부름, 이는 브라우저에서 비표준으로 제공하는 것이었음
- 이를 통해서 프로토타입에 대신 접근하도록 해주는 값임, 마치 getter, setter처럼 프로토타입에 접근하기 용이한 값(일종의 프로토타입의 접근제어자)
- 하지만 사용을 권장하지 않음, 대신
getPrototypeOf
혹은 setPrototypeOf
사용을 권장함
- 해당 메소드들은 Object에서부터 시작되는 메소드들임, 이를 통해서 프로토타입의 접근해서 처리하는것을 권장함(사용하게 되는 경우)
프로토타입 체인
{
const a = 'outer';
{
const a = 'inner';
console.log(a);
}
}
[1, 2, 3]
.sort((a, b) => a - b)
.filter((e) => typeof e === 'number')
.map((e) => e + 'EA');
- 위와 같이 체이닝을 하는데 프로토타입 역시도 비슷하게 체이닝을 할 수 있음, 이는 array가 Array 타입이면서 객체가 될 수 있는 구조이기에
hasOwnProperty
같은 객체의 메소드도 사용 가능함(array < Array < Object)
- 즉, 그러한 체이닝 구조를 가지고 있다고 볼 수 있음
const array = [ ]
array.push(10)
array.push(20)
array.hasOwnProperty(0)
array instanceOf Object
- 아래와 같이도 활용이 될 수도 있는 것임, 아무것도 내부의 프로토타입을 정의하지 않아도, 다양한 메소드를 사용할 수 있는 것이 체이닝이 되어 있기 떄문이라고 볼 수 있음
const animal = {
sayName() {
return 'ANIMAL';
},
};
const dog = Object.create(animal);
dog.sayName()
프로토타입 확장
- 확장은
extends
키워드를 쓰고, 상속이라고도 많이 표현함(부모 => 자식 관계를 많이 따짐, 부모 => 확장 => 자식 느낌으로)
- 프로토타입을 확장한다고 해도 프로토타입을 직접 확장하진 않고 아래와 같이 확장을 함
function Animal(name, sound) {
this.name = name;
this.sound = sound;
}
Animal.prototype.getInfo = function() {
return (
this.name +
'가(이)' +
this.sound +
' 소리를 낸다.'
);
};
function Friends(name, sound) {
Animal.call(this, name, sound);
}
Friends.prototype = Object.create(
Animal.prototype,
);
Friends.prototype.constructor = Friends;
const dog = new Friends('개', '멍멍');
const cat = new Friends('고양이', '냐옹');
dog.getInfo();
cat.getInfo();
dog.constructor.name;
dog instanceof Friends;
dog instanceof Animal;
- 클래스에서 좀 더 편리하게 사용해서 쓸 수 있음, 프로토타입도 확장이 될 수 있음을 이해하면 됨