Prototype과 __proto__ 이해하기(1)

goggling·2022년 1월 16일
1

whereTogo?

목록 보기
2/3
post-thumbnail

javascript에서 상속의 개념을 갖게 해주는 prototype.
정확한 동작 방식보다는 개념에 초점을 맞추어 생각해본 글입니다...

prototype은 일종의 유전자 같은 개념이다.

  • (부모입장) prototype : 유전자, 자손에게 넘겨주고픈 메소드,변수를 정의함.
  • (자식입장) __proto__(property) : 내가 받은 유전자 접근하기. 부모에게 유전받은 prototype을 참조할 수 있다.

프로토타입(prototype)이란?

ECMA-262에서 prototype은 ‘object that provides shared properties for other objects’로, 다른 객체에 공유 프로퍼티(메서드 포함)를 제공하는 객체이다.

재해석 : prototype는 일종의 유전자와 같이 자신을 조상으로 하는 다른 객체에게 공유(유전자면, 전달이라는 의미가 좀 더 쉽겠지만, 실제 공유와 더 가깝다)하는 property 혹은 method 객체이다.

생물학적 유전자와는 당연 차이가있다...

  • 반드시 유전됨 (맨델 머시기 법칙없이 무조건 부모의 유전자를 물려받음)
  • 변경 가능 (내가 전달받은 유전자 조작 가능)
  • 변경시, 이 유전자를 갖는 모든 객체의 유전자가 변경됨 (전달이 아닌 공유의 개념) => (엄마에게 받은 유전자를 내가 임의로 조작하는 순간, 나뿐만 아니라 오빠의 유전자도 변경됨)

❓ 객체의 유전자인 프로토타입도 객체라는 것이죠?

❗ 네(니오), 넘겨주고싶은 유전자가 없다면? null이고, 있으면 객체의 형태로 존재한다.

  • prototypenull 혹은 객체

좀 더 자세한 내용은... Prototype과 proto 이해하기(2)에서...


__proto__란?

모든 객체는 __proto__를 통해 자신이 물려받은 [[Prototype]] 값에 접근할 수 있다.
재해석 : __proto__라는 프로퍼티로 유전자 접근이 가능하다.

하지만 [[Prototype]] 내부 슬롯에는 직접 접근이 불가하다. 이는 프로토타입 체인의 단방향을 지키기 위해서다. 만약 직접 접근가능하다면, 서로가 서로의 프로토타입이 되면서 프로토타입 체인이 무한으로 돈다. 따라서 __proto__ 프로퍼티로만 접근할 수 있다.

자식이 자신이 받은 유전자를 확인할 수 있는 property 이다. 애초 자식 오브젝트를 만들 때, 명시적으로 선언하지 않지만 자바스크립트 엔진이 내부적으로 알아서 할당해준다.

따라서 자식객체.__proto__를 내가 정의해주지 않았어도, 이미 정의가 되어있다. (내가 태어나면, 자동적으로 부모님의 유전자가 내 안에 있는것처럼 객체 혹은 null로 정의되어있음)

예를 들어, const str_instance = new String("abc");을 하면, str_instanceString이라는 부모로부터 낳아진 자식이다. 따라서 __proto__String.prototype이 이미 자동적으로 잘 정의되어진다.

const str_instance = new String("abc");
String.prototype === str_instance.__proto__ //true

결국, String 오브젝트가 자식에게 넘겨주고싶던 유전자 String.prototypestr_instance가 받은 유전자 str_instance.__proto__는 같다.


자식은 부모의 prototype을 활용할 수 있나요?

재번역하면, 자식은 부모로부터 자기가 물려받은 유전자를 활용할 수 있나요? yes! 부모뿐만 아니라 부모의 부모, 부모의 부부부부부모 유전자까지 활용가능하다.

프로토타입 체인(prototype chain) 구조로 활용 가능한데, chaining rule(연쇄법칙)을 상상하면 개념은 쉽다.

  1. 내가 있으면 내 변수나 메소드를 활용
  2. 없으면 부모 변수,메소드 .__proto__ 로 접근
  3. 없으면 부부모 .__proto__.__proto__ 로 접근
    ...(최초 부모까지 계속 접근 시도)

즉, 객체는 chain rule(연쇄법칙) 구조로 property나 method를 활용한다.

  • 나부터 최초조상까지 연쇄적으로 변수/메소드를 훑다가 있으면 활용
  • 끝까지 없으면 변수이면 undefined, 메소드이면 TypeError를 반환한다.
const str_instance = new String("abc");
//자식에게 존재
console.log(str_instance[0]) //a
//자식에게 없고 부모에게 존재
console.log(str_instance.indexOf("c")) //2
//자식에게 없고, 부모,조부모에게 있지만 더 측근인 부모 method활용하고 조부모 prototype 접근 안함
console.log(str_instance.valueOf()) //'abc'
//자식에게 없고, 부모에게 없고 조부모 prototype에 존재
console.log(str_instance.hasOwnproperty())//false 
//자식,부모,조부모,,...., 모두 없음
console.log(str_instance.count());//error, 함수없음
//자식,부모,조부모,,...., 모두 없음
console.log(str_instance.long);//undefined

prototype이 변경되면 자손들은 어떤 변화가 있나요?

재해석 : 유전자가 변경되면, 이 유전자를 갖는 자손들은 어떻게 되나요?

const str_instance_before = new String("abc");
console.log(str_instance_before.sayHi()); //error,자식 그리고 모든 조상에 정의되지 않음.

String.prototype.sayHi = function(){
  return "hi!"}

console.log(str_instance_before.sayHi()); //"hi!"

const str_instance_after = new String("cde");
console.log(str_instance_after.sayHi()); //"hi!"

이 유전자를 갖는 자식뿐만 아니라 모든 자손의 유전자__proto__가 변경됨


[Prototype과 __proto__ 이해하기(2)](aa) 에서는 개념뿐만 아니라 내부적인 구조와 함께 이해를 도전해보자

내용상 오류가 있으면 알려주시면 감사합니다.

0개의 댓글