프로토타입

김정민·2022년 4월 10일
1
post-thumbnail

초반 JavScript는 클래스라는 개념이 없었다, 그래서 기존의 객체를 복사하는 방식으로 새로운 객체를 생성하는 프로토타입 기반의 언어였다.

프로토타입의 원리는 간단하다. 모든 객체는 자신의 프로토타입 객체를 가지고 있으며 프로토타입 객체의 프로퍼티들을 사용할 수 있다. 그리고 이 과정은 프로토타입 링크를 통해서 구현된다.

var foo = {name : "foo"}; // foo 라는 객체를 생성.
foo.prototype.a='hello world';
console.log(foo.a);

해당 코드의 결과는 Error가 출력된다.

function foo(x) {
    this.x = x;
};

var A = new foo('hello'); 
console.log(A.x);
> hello

console.log(A.prototype.x)
> syntax error

해당 코드도 보게되면 Error가 출력된다.


당연한 결과이다. prototype 프로퍼티는 Constructor가 가지는 프로퍼티 이다. 그리고 함수객체만 이 프로퍼티를 가지고 있다고 했다.
위 코드속 A객체는 함수객체가 아니다. foo라는 원형을 이용하여 함수객체를 통해 만들어진 Object객체에 확장된 단일 객체일 뿐이다.


즉 A는 prototype 프로퍼티를 소유하고 있지 않기에 A.prototype.x가 syntax error 인 것이다.

위 코드는 new 연산자를 사용해 A라는 함수를 이용해 새로운 객체를 B를 변수에 담는 코드이다. console로 찍혀있는 __proto__constructor 이 둘을 주의깊게 봐야한다.


또한 우리가 함수객체를 생성할 때 그 객체에는 prototype이라는 object가 자동으로 생성된다. (밑 그림과 같이)
그리고 그 prototype에는 역시 constructor라는 객체가 자동으로 생성되어 서로가 서로를 참조할 수 있게 된다.

정리하자면

Prototype Object 라는 새로운 객체를 Cloning 하여 만들어낸다. 프로토타입이 객체를 만들어내기위한 원형이라면 이 Prototype Object 는 자기 자신의 분신이며 자신을 원형으로 만들어질 다른 객체가 참조할 프로토타입이 된다. 즉 객체 자신을 이용할 다른 객체들이 프로토타입으로 사용할 객체가 Prototype Object 인 것이다. 즉 위에서 언급한 __proto__라는 prototype 에 대한 link는 상위에서 물려받은 객체의 프로토타입에 대한 정보이며 prototype 프로퍼티는 자신을 원형으로 만들어질 새로운 객체들 즉 하위로 물려줄 연결에 대한 속성이다.

  • __proto__ - 자신을 만들어낸 객체의 원형과 연결된 속성이다.
  • constructor - 생성자로써, 자신을 만들어낸 객체와 연결된 속성이다.
  • prototype - 자신을 원형으로 만들어진 새로운 객체들과 연결된 속성이다.

1 prototype


지금까지 내용을 잘 이해하고 있다면 예제1의 this.x 는 A의 프로퍼티 x 이고, 예제2 는 A의 prototype Object 에 연결된 x 라는 것을 이해 할 수 있을것이다. 그럼 왜 굳이 prototype 을 사용하여야 하는가?

  • 예제1 : B,C는 A를 프로토타입으로 사용하기위해 A의 prototype object를 사용한다. 그리고 이 prototype object는 A가 생성될 당시의 정보만을 가지기 때문에 예제1은 hello가 출력된다.
    그래서 A.x를 수정하여도 A의 prototype object는 변경되지 않기 때문에 B,C는 hello만 참조하는 것

  • 예제2 : 결과가 world가 되는 이유도 같은 이유다. A.prototype은 A의 prototype object를 참조하는 녀석이기에 A.prototype.x 를 정의한다는 것은 A의 Prototype Object를 직접 이용하게 되는 것이고 그에 따라서 A의 Prototype Object를 프로토타입으로 이용하여 만들어지는 B,C 가 알고 있는 x 는 function () {console.log('world');} 가 되는 것이다.

2 체인닝


위 예제에서 A의 Prototype Object의 x 메소드를 재정의 하였을 때 B,C객체도 그 영향을 받는다는 것을 알 수 있다. 그 이유는 프로토타입 체인에 의한 공유 때문이다. 아래의 그림을 잘 봐보기 바란다.

프로토타입 상속에 대한 구조 이해는 가능하리라 믿는다. 여기서 유심히 봐야할것은 A Prototype Object 가 소유한 Constructor 다. A Prototype Object의 Constructor는 A 객체의 생성자 함수이다. 즉 이를 통해 만들어지는 객체들은 A 객체가 생성될 당시 소유하고 있지 않은 x 라는 메소드를 가질수 없다. x는 A.prototype 를 이용하여 A Prototype Object에 추가 되어진 메소드다. 하지만 이 x 메소드는 프로토타입 체인에 의한 공유 메소드

하지만 A 객체가 생성당시 x 라는 메소드 혹은 의미있는 프로퍼티에 대한 정의가 포함된 내용을 가지고 있다면 이들은 공유가 아닌 상속된다

위 예제는 위는 공유 아래는 상속이라 볼 수 있다.


이처럼 공유와 상속의 구분을 정확히 이해하고 사용하는 것은 매우 중요하다. 이들을 햇갈리게 되면 후에 프로토타입 재정의에 따른 원하지 않는 참혹한 결과를 가져다 줄수도 있기 때문이다.

3. 체인닝 동작

foo.country 값에 china를 저장하면 Person.prototype의 country 프로퍼티가 변경되는것이 아니라 foo 객체에 country 값이 동적으로 생성된다.

마무리

정리하면서 이외에도

object.create 와 new의 차이

다중상속 관련내용도 궁금하게 되었지만 나중에 시간이 되면 포스팅,할 예정

1개의 댓글

comment-user-thumbnail
2022년 4월 12일

좋은 정보 감사합니다

답글 달기