본문 바로가기

Programming/Javascript

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

javascript logo image

 

 

앞서 작성한 예제 코드를 정리해 보겠습니다. 다음과 같이 subClass 함수가 어느 정도 모양새를 갖추었습니다.

 

function subClass(obj) {

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

    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);
        }
    };


    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 parent = this; 라인이 작성되어 있는데, 최상위 클래스를 Function으로 받아서 클래스를 형성해 나가야 하는 것을 가정했죠? 하지만 여기에는 그러한 처리가 되어 있지 않습니다.

 

우리가 this 바인딩 아티클에서 배웠듯이, 만일 이 상태로 특정 부모 클래스가 없는 상태에서 subClass를 호출하게 되면 이 this는 전역 객체(window / Node.js의 경우 global)를 바인딩하게 됩니다. 이 경우에 대해서 분기를 두어 처리해 주는 코드를 추가해 보겠습니다. 

 

 

if(this === window) {
  var parent = Function;
} else {
  var parent = this;
}

 

 

위와 같이 parent에 대한 분기를 주어, 최상위 계층 클래스에 대한 정의를 구체화시켜 보았습니다. if else문을 축약하여 사용한다면, 아래와 같이 바꾸어 줄 수도 있습니다.

 

var parent = this === window ? Function : this;

 

 


 

이제 완성된 subClass함수는 다음과 같습니다. 참고로 하나 바뀐 라인이 있는데, child.subClass = arguments.callee; 입니다. arguments.callee는 현재 호출된 함수, 즉 subClass를 의미합니다. child.subClass는 subClass 함수를 참조하게 됩니다.

 

function subClass(obj) {

    var parent = this === window ? Function : this;

    var F = function() {};

    var child = function() {

        var _parent = child.parent;

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

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


    F.prototype = parent.prototype;
    child.prototype = new F();
    child.prototype.constructor = child;
    child.parent = parent;
    child.subClass = arguments.callee;

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

    return child;

}