프로토타입

미마모코딩·2022년 6월 7일
0

18강 프로토타입

목록 보기
1/1
post-thumbnail

내부슬롯

우선 Prototype을 공부하기전에 모든 객체는 [[Prototype을]]이라는 내부슬롯을 가진다.

[[Prototype을]]에 저장되는 프로토타입은 객체 생성 방식에 의해 결정된다.

즉 객체가 생성될 때 객체 생성 방식에 따라 프로토타입이 결정되고 [[Prototype을]]에 저장된다.

또한 모든 객체는 하나의 포로토타입을 갖는다.

그리고 모든 프로토타입은 생성자 함수와 연결되어 있다.

__ proto __

__ proto __는 접근자 프로퍼티이다.

__ proto __는 getter/setter 함수라고 부르는 접근자 함수

([[Get]],[[Set]]) 프로퍼티 어트리뷰트에 할당된 함수를 통해

[[Prototype을]] 내부 슬롯의 값 , 즉 프로토 타입을 취득하거나 할당한다.

__ proto __는 접근자 프로퍼티는 상속을 통해 사용된다.

모든 객체는 프로토타입 계층 구조인 프로토타입 체인에 묶여있다.

자바스크립트 엔진은 객체의 프로퍼티에 접근하려 할 때 해당 객체에 접근하려는

프로퍼티가 없다면 , 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로

탐색한다.

또한 프로토타입 체인은 단방향 링크드 리스트로 구현되어야한다.

코드로 예를 들어보자.

<script>
const parent = {};
const child = {};
//child의 프로토타입을 parent로 설정
child.__proto__ = parent;
//parent의 프로토타입을 child로 설정
parent.__proto__ = child; // TypeError:Cyclic__proto__ value
</script>

여기서 에러가 나는 이유는 parent와 child가 서로가 자신의 프로토타입이 되는 비정상적인 프로토타입 체인이 만들어지기에 에러가 발생한다.

그렇기 때문에 단방향 링크드 리스트로 구현되어야하는 이유이다.

Object는 프로토타입 체인의 종점이라는 사실을 꼭 기억하자.
위 예시코드에선 즉 Object - parent - child 구조이다.

__proto__를 대체할 getPrototypeOf

__proto__ 접근자 프로퍼티 대신 프로토타입의 참조를 취득하고 싶은 경우는 어떻게 처리하는게 효율적일까?

Object.getPrototypeOf 메서드를 사용하고 프로토 타입을 교체하고 싶다면
Object.setPrototypeOf 메서드를 사용할 것을 권장한다.

아래 예시 코드를 보자.

<script>
const obj = {};
const parent = { x: 1};
//obj 객체의 프로토타입을 취득 
Object.getPrototypeOf(obj); //obj.__proto__;
//obj 객체의 프로토타입을 교체
Object.setPrototypeOf(obj,parent); //obj.__proto__ = parent
console.log(obj.x); // 1
</script>

Object.getPrototypeOf 메서드와 Object.setPrototypeOf 메서드는

get Object.prototype.__proto__와 set Object.prototype.__proto__의 처리

내용과 정확하게 일치한다.

constructor

화살표함수는 non-constructor이기 때문에 새로운 인스턴스를 만들 수 없다.

또한 non-constructor는 prototype 프로퍼티를 소유하지 않는다.

생성자 함수로 생성된 인스턴스는 프로토타입의 constructor 프로퍼티에 의해

생성자 함수와 연결된다.

이때 constructor 프로퍼티가 가리키는 생성자 함수는 인스턴스를 생성한 생성자 함수다.

아래 코드로 예를 들어보자.

<script>
//obj 객체를 생성한 생성자 함수는 Object다.
const obj = new Object();
console.log(obj.constructor === Object); // ture
//
</script>

이렇듯 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재한다.

프로토타입의 생성 시점

프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성된다.

즉 생성자 함수로서 호출할 수 있는 함수 , constructor는 함수 정의가 평가되어 ,

함수 객체를 생성하는 시점에 프로토타입도 더불어 생성되는 것이다.

프로토타입 체인

다음 예제를 살펴보자.

<script>
function Person(name){
this.name = name;
}

//프로토타입 메서드
Person.prototype.sayHello = function(){
console.log(`Hi ! my name is ${this.name}`);
};

const me =new Person("Lee");

//hasOwnProperty는 Object.prototype의 메서드이다.
console.log(me.hasOwnProperty("name")); //true
</script>

person 생성자 함수에 의해 생성된 me객체는 Object.prototype의 메서드인 hasOwnProperty를 호출할 수 있다.

이것은 me 객체가 person.prototype뿐만 아니라 Object.prototype도 상속받았다는 것을 의미한다.

me에서 없기때문에 person.prototype에서 찾고 최종적으로 없다면 Object.prototype에서 찾게 되는것이다.

instanceof 연산자

instanceof 연산자는 이항 연산자로서 좌변의 객체를 가리키는 식별자,우변에 생성자 함수를 가리키는 식별자를 피연산자로 받는다.

즉 이런 형식이다 .

객체 instanceof 생성자함수

우변의 생성자 함수의 prototype에 바인딩(묶여있는,엮여있는) 객체가 좌변의 객체의 프로토타입 체인 상에 존재하면 true 아니면 false로 평가된다.

코드로 예를 들어보자.

<script>
function Person(name){
this.name = name;
}
const me = new Person("Lee")
//person.prototype이 me 객체의 프로토타입 체인 상에 존재하므로 true이다.
console.log(me instanceof Person) // true

//Object.prototype이 me 객체의 프로토타입 체인 상에 존재하므로 true이다.
console.log(me instanceof Object) // true
</script>

이렇듯 instanceof 연산자를 통해 프로토타입 체인의 여부를 확인할 수 있다.

길고 어려웠던 프로토타입의 내용인 만큼 여러 블로그와 강의도 병행해서 공부한다면

깊은 이해를 할 수 있을것이다.

0개의 댓글