nobodj
No SG 운동

javascript : prototype의 이해 November 2, 2018

javascript는 prototype모델기반을 상속한다.

우선 알아야할 점.
* function도 하나의 객체이다.
* 함수객체는 선언과 동시에 prototype속성으로 prototype object를 생성해서 참조한다.

* prototype object는 new 연산자를 통해 객체를 생성할 경우, 원형으로 삼는 객체.
* constructor속성으로 함수객체를 참조함.
* (중요)new 연산자를 통해 새로운 객체가 생성되면, 새로운 객체의 __proto__속성으로 다시 prototype object를 참조함 -> prototype chain을 가능하게 하고, 최고 조상 Object객체까지 연결됨.

function Person(){}//함수객체 선언.
//prototype속성으로 빈객체(Person Prototype Object)를 생성해 참조함.
//Person Prototype Object의 constructor로 Person 생성자 함수 참조
Person.prototype.eyes = 2;
Person.prototype.nose = 1;
var kim = new Person();//kim객체 생성시 __proto__속성으로 Person Prototype Object를 참조한다.

예제1)

var A = function() {
    this.x = function () {
        console.log('hello');
    };
};

A.x=function() {
    console.log('world');
};

var k = new A();
k.x();
> hello

world가 나오지 않는 이유는 A prototype object를 원형으로 객체 k가 생성되었고, 이때 참조하는 constructor속성의 생성자함수의 x속성은 function () { console.log('hello'); };이기 때문이다. 최초 함수선언시 이미 셋팅이 끝났다.
그럼 A.x는 뭘 한거냐? A라는 함수객체의 속성x를 부여한 것이다.

A.x();
> world

즉, 함수객체와 생성자함수(prototype의 constructor속성)는 별개다.

예제2)

var A = function() {
    this.x = function () {
        console.log('hello');
    };
};
A.prototype.x = function(){
    console.log('world');
}
new A().x();
> hello
new A().__proto__.x();//참조하고 있는 prototype Object의 x속성 호출
> world

이것도 world가 나오지 않는 이유는 hello출력속성 x는 객체(this)에 속성이고, world출력속성 x는 prototype object(부모)의 속성이므로, 우선순위가 this에 있는 것이다.

예제3)
prototype선언은 원칙적으로 관련선언은 원칙적으로 함수 바깥에서 해야 한다. 그렇지 않을 경우의 오류를 살펴본다.

정상적인 사용

function A(){};
A.prototype.x = function(){
    console.log("A의 prototype객체의 x호출");
}
function B(){};
B.prototype = A.prototype;
new B().x();
> A의 prototype객체의 x호출
B.prototype == A.prototype        
> true

함수안에서 prototype함수를 지정했지만, 정상동작한다.
생성된 객체 new B()의 proto속성이 가리키는 prototype object에 x속성 정상바인딩

function A(){};
A.prototype.x = function(){
    console.log("A의 prototype객체의 x호출");
}
function B(){
    B.prototype.x = A.prototype.x;
}
new B().x();
> A의 prototype객체의 x호출
B.prototype == A.prototype
> false

잘못된 예시
첫번째 만든 객체 b1.x()는 오류가 나고, 두번째 만든 객체 b2.x()는 정상동작한다.

function A(){};
A.prototype.x = function(){
    console.log("A의 prototype객체의 x호출");
}
function B(){
    B.prototype = A.prototype;
}

B.prototype == A.prototype;
> false
var b1 = new B();
var b2 = new B();
b1.x();
> Uncaught TypeError: (intermediate value).x is not a function
B.prototype == A.prototype        
> true
b2.x();//두번째호출시에는 생성자함수B의 prototype이 A.prototype으로 변경되었음.
> A의 prototype객체의 x호출

함수 객체 B가 선언되면, 자동으로 prototype속성에 생성된 빈객체(임의로 originalProto 이름으로 부르겠다)가 참조된다.(이 객체의 constructor로 함수B가 역참조)
그리고 new B() 호출되면, orignalProto를 원형으로 하는 객체 b1이 생성된다. 이때, 생성자함수(constructor속성)가 실행되면서
B.prototype = A.prototype;가 실행된다. 다음번 객체생성시에나 적용될 것이고, 이미 생성된 객체 b1의 proto는 originalProto를 참조하므로, A.prototype.x속성은 사용할 수 없다. 다시 얘기하면, b1의 protochain에 x속성은 없다.

참조 : Javascript 기초 – Object prototype 이해하기

No Comments on javascript : prototype의 이해