초반 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의 this.x 는 A의 프로퍼티 x 이고, 예제2 는 A의 prototype Object 에 연결된 x 라는 것을 이해 할 수 있을것이다. 그럼 왜 굳이 prototype 을 사용하여야 하는가?
prototype object
를 사용한다. 그리고 이 prototype object
는 A가 생성될 당시의 정보만을 가지기 때문에 예제1은 hello가 출력된다.prototype object
는 변경되지 않기 때문에 B,C는 hello만 참조하는 것prototype object
를 참조하는 녀석이기에 A.prototype.x 를 정의한다는 것은 A의 Prototype Object
를 직접 이용하게 되는 것이고 그에 따라서 A의 Prototype Object
를 프로토타입으로 이용하여 만들어지는 B,C 가 알고 있는 x 는 function () {console.log('world');} 가 되는 것이다.
위 예제에서 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 라는 메소드 혹은 의미있는 프로퍼티에 대한 정의가 포함된 내용을 가지고 있다면 이들은 공유가 아닌 상속된다
위 예제는 위는 공유 아래는 상속이라 볼 수 있다.
foo.country 값에 china를 저장하면 Person.prototype의 country 프로퍼티가 변경되는것이 아니라 foo 객체에 country 값이 동적으로 생성된다.
정리하면서 이외에도
object.create 와 new의 차이
다중상속 관련내용도 궁금하게 되었지만 나중에 시간이 되면 포스팅,할 예정
좋은 정보 감사합니다