클래스는 상속을 할 수 있다. 프로토타입 객체에도 상속이 들어간다. 이러한 프로토타입을 연속적으로 묶어서 쓸 수 있다.
const div = document.createElement("div")
div.__proto__
div.__proto__.__proto__
div.__proto__.__proto__.__proto__
div.__proto__.__proto__.__proto__.__proto__
div.__proto__.__proto__.__proto__.__proto__.__proto__
이러면 각각의 프로토타입들의 상위 프로토타입을 조회해 볼 수 있다. 저 값들은 object
타입일 것이고 벗어나면 null일 것이다.
인스턴스 객체에 특정 프로퍼티에 접근할 때 해당 객체에 프로퍼티가 없으면 [[Prototype]]
내부 슬롯의 참조를 따라 상위 프로토타입의 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라고 한다.
즉, 상속받은 인스턴스 객체에 별도의 속성이나 프로퍼티를 따로 지정해주는 않으면 부모 클래스의 프로토타입의 속성과 메서드를 가져와서 있으면 사용한다.
- 프로토타입 체인은 체인에서 먼저 찾은 속성을 반환한다.
const arr = new Array(); // new 키워드를 이용
console.log(arr); // => [];
const newArr = []; // 빈 배열 할당
console.log(newArr); // => [];
Array 인스턴스를 만드는 두 가지 방법이다. 이 둘은 같을까? 물론 같지 않을 것이다. 값이 같아도 참조 자료형이기 때문에 다른 주소값을 가지고 있다.
arr === newArr // => false;
하지만, 이 둘은 배열이라는 클래스에서 상속받은 인스턴스들이 아닌가? 정확히 말하자면 배열 클래스에서 상속받은 Prototype 객체를 공유하지 않을까? 알아보자.
arr.__proto__ === newArr.__proto__ // => true;
같은 프로토타입을 공유한다!
arr.__proto__.constructor === newArr.__proto__.constructor // => true;
물론, 같은 부모 클래스에서 상속 받을 것을 확인할 수 있다.
배열의 프로토타입 객체는 무슨 type일까?
typeof arr.__proto__. // => 'object'
휴~ 프로토타입 객체이니까 아무래도 object를 반환하겠지...
Array.isArray(arr.__proto__); // => true
?!!!
배열이 반환되었다...
배열이기때문에 한번 인덱스를 갖는지 살펴보았다.
arr.__proto__[1] // => undefined;
헉... 배열이지만 인덱스로 부르는게 적용되지 않는다!
그럼 객체라고 생각하고 불러보겠다.
arr.__proto__["concat"] // => 𝑓 concat() { [native code] }
생긴 건 배열처럼 생겼지만 [[Prototype]] : Object 내부 프로토타입 슬롯을 가지고 있다!
배열은 특별해서 그냥 배열 인스턴스의 프로토타입은 그냥 특별하게 적어 놓은 것인가?
알다가도 모를 JavaScript!!!