대망의 프로토타입. 사실 이전에 OOJS를 다루며 설명해놓은 글이 있긴하다.
더 간략히 요약해보는 시간을 가져보자.
클래스 기반 객체지향이 아닌 프로토타입 기반 객체지향
=> 원시타입을 제외한 모든 것이 객체.
명령,함수 목록으로 보는 절자치향에서 벗어나 여러개의 독립적 단위(객체)의 집합으로...
=> 쉽게 말해 클래스에서 기능을 다 묶고 객체를 생성(인스턴스화) 하면, 사용할땐 현실처럼 내부 동작을 몰라도 사용할 수 있다.
내부 데이터(상태)는 프로퍼티, 객체의 내부 데이터를 조작하는 함수(동작)을 메소드라고 함.
객체는 독립적일 수도있고, 다른 객체와 관계를 맺을수도, 다른 객체의 상태나 동작을 상속받아 사용할수도 있다.
=> 재사용성이 용이하고, 의존성 주입이 쉽다.
객체지향에서 자주쓰는 말이다. 살짝 헷갈린다.
그렇다.
클래스 기반 객체지향에선 상속을 통해 부모 클래스의 프로퍼티와 메소드를 받아옴.
이를 JS에선 프로토타입으로 구현함.
둘 다 불필요한 중복을 제거.
But, 프로토타입은 자식클래스가 직접 상속받는 것이 아님. 프로토타입이 갖고있는걸 나눠쓴다.
따라서 클래스 기반 객체지향보다 메모리 낭비를 덜함.
프로토타입 객체지향이라는 뜻은, 우리가 사용하는 객체타입도 결국프로토타입이 존재함을 뜻함.
=> [[Prototype]]
내부 슬롯.
__proto__
접근자로 접근 가능.
ES6이후에는get, setPrototypeOf()
를 사용
참고로 이렇게 프로토타입을 수정하는건 권장되지 않음.
Object.create()
로 새로운 참조를 생성해야한다.
=> 프로토타입체이닝을 모두 바꿔야하기때문
접근자는 곧 get,set
을 사용한다는 뜻.
read-write가 가능하게 만든 이유는 내부적으로 상호참조를 방지하기 위해서.
a,b가 서로를 프로토타입으로 참조하면 순환참조 에러.
나머지 사항은 이렇다.
prototype
은 생성될 인스턴스의 프로토타입constructor
프로퍼티를 가짐. 생성자함수를 가리킴.{}
는 생성자함수로 생성된 건 아니지만, constructor
가 제대로 들어가있다.{}
: Object.prototype
Object()
: Object.prototype
function(){this...}
: 생성자함수 prototype
에 바인딩 되어있는 객체스코프체인처럼 프로토타입도 계속해서 프로토타입 참조를 타고(상위) 호출한 프로퍼티를검색한다.
=> 상위의 모든 프로토타입은 전부 상속받았다고 보면 된다.
최상위 프로토타입 객체는 Object.prototype
이다.
따라서 모든 객체가 이를 상속받는다.
=> 그 위는 null
이다
본래는 생성자함수의constructor
인 Person이 프로토타입이어야함.
__proto__
로 변경할수도있다.
둘다 권장x
객체 instanceof 생성자함수
이렇게 사용함.
=> 이 인스턴스가 생성자함수로 만든것이냐~
생성자함수의 prototype에 바인딩된 객체가 프로토타입 체인상에 존재하면 true다.
아까 설명했던 Object.create()
은 명시적으로 프로토타입을 선언하여 새로운 객체를 생성한다.
Object.create(프로토타입);
장점이 많다.
여담으로 ESlint는 빌트인 메소드를 바로 사용하는걸 권장하지 않음
Object.create(null)
로 종점 프로토타입을 가진 객체생성이 가능하기때문.
=> 이렇게 생성한 객체로 빌트인 메소드를 호출하면 에러가난다.
클래스에서 static
을 사용하여 선언한 정적 메소드는 사실 이렇게 구현된다.
function Person(name){
this.name = name;
}
Person.staticMethod = function (){
return "hi";
}
Person.staticProp = "bye";
const person = new Person("kim");
person.staticprop // ...undefined
person.staticMethod() // is not a function...
인스턴스에서는 참조 불가. 생성자함수에서 참조 가능.
in
연산자를 사용하여 확인한다.for...in
메소드는 객체를 순회하며 [[Enumrable]]
한 프로퍼티를 열거함.(상속받은 프로퍼티도 가능).Object.keys, values, entries()
는 고유한 객체 프로퍼티만 열거.hasOwnProperty
는 상속받지 않은 고유한 객체의 프로퍼티인지 확인참고로 모던 브라우저는 숫자인 프로퍼티 키에 대해서 정렬함!