본문 바로가기

Programming/Javascript

13. Javascript 객체지향 프로그래밍(5) - subClass 구현하기 3

javascript logo image

 

앞서 살펴본 subClass 예제 코드에서, 부모 객체의 생성자를 함께 호출하는 선언문 내용을 추가하는 과정을 자세하게 살펴보도록 하겠습니다. 이 과정에서 몇 가지 한계점을 발견하고, 문제점을 보완하는 순서로 진행하겠습니다. 우선 기존 작성 예제 코드를 다시 한번 살펴보겠습니다. 

 

function subClass(obj) {

    var parent = this;
    var F = function() {};

    var child = function() {};

    F.prototype = parent.prototype;
    
    child.prototype = new F();
    child.prototype.constructor = child;
    child.parent = parent.prototype;
    child.parent_constructor = parent;

    for(var i in obj) {
        if(obj.hasOwnProperty(i)){
            child.prototype[i] = obj[i];
        }
    }

    return child;

}

 

이제 여기에서 빈 객체로 작성된 var child = function( ) { }; 라인에 부모 객체 생성자 선언에 대한 코드를 작성해 추가해 보도록 하겠습니다. 

 

 


 

 

var child = function() {
        if(parent._init) {
            parent._init.apply(this, arguments);
        }
        if(child.prototype._init) {
            child.prototype._init.apply(this, arguments);
        }
};

 

위와 같이 각 클래스의 생성자로 선언된 _init을 찾고, 있을 경우 생성자를 apply를 통해 실행하는 코드를 작성했습니다. 단, 여기서도 문제가 하나 발생하게 되는데요, 바로 프로토타입 체이닝 때문에 해당 위치에 _init이 없다면 의도치 않게 상위 클래스의 _init 함수를 찾아 실행하는 경우가 발생할 수 있습니다. 이러한 상황을 방지하기 위해서, hasOwnProperty 함수를 활용하게 됩니다. 

 

 

var child = function() {
        if(parent.hasOwnProperty("_init")) {
            parent._init.apply(this, arguments);
        }
        if(child.prototype.hasOwnProperty("_init")) {
            child.prototype._init.apply(this, arguments);
        }
    };

 

 

하지만 위와 같은 경우라고 하더라도, 여전히 문제가 발생합니다. 이 경우는 오로지 부모 클래스 한 개, 자식 클래스 한 개만이 존재하는 경우에만 정상적으로 작동합니다. 자식 클래스에서 subClass를 이용하여 또 하나의 자식 클래스를 생성하게 되면 최종 부모 클래스는 호출하지 못합니다. 이를 해결하기 위해, 재귀적으로 부모 함수를 호출하는 코드로 수정해야 합니다. 

 

 

var child = function() {

        var _parent = child.parent_constructor;

        if(_parent && _parent !== Function) {
            _parent.apply(this, arguments);
        }

        if(child.prototype.hasOwnProperty("_init")) {
            child.prototype._init.apply(this, arguments);
        }
    };