본문 바로가기

Programming/Javascript

13. Javascript 객체지향 프로그래밍(2) - 프로토타입 상속 구현 2

javascript logo image

 

지금까지 새로 생성된 객체(자식 객체) 들이 부모 객체(생성자 함수)의 메서드를 그대로 '상속'받아 사용하는 케이스를 살펴보았습니다. 여기에 하나 더 필요한 기능이 있죠. 부모 객체를 상속하는 자식 객체들이 자신들만의 고유의 메서드를 추가하는 기능입니다(또는 기존 메서드를 재정의하여 자신만의 메서드로 사용).

 

사실 이 기능은 크게 어려울 것이 없습니다. 아래와 같이 특정 객체의 메서드를 선언하고 정의하면 끝나는 일이니까요. 

 

hypeBoy.setName = function(value) { //... };
hypeBoy.getName = function() { //... };

 

하지만 이 단순한 방법은 코드가 복잡해지게 만드는 원인이 됩니다. 이제부터는 jQuery의 extend( ) 함수를 사용하는 방법과 그 구조를 살펴보도록 하겠습니다. 

 

 


 

우선 jQuery 1.0의 extend 함수에 대한 선언을 살펴보고 라인 별로 상세 내용을 살펴보도록 하겠습니다.

 

jQuery.extend = jQuery.fn.extend = function(obj, prop) {
    if( !prop ) { 
        prop = obj; 
        obj = this; 
    }

    for( var i in prop ){
        obj[i] = prop[i];
    }

    return obj;
}

 


 

 

우선 가장 첫 번째 줄을 살펴보도록 하겠습니다. 

jQuery.extend = jQuery.fn.extend = ...

 

여기서 jQuery.fn은 jQuery.prototype을 의미하게 됩니다. 그렇다는 것은 우리가 배웠던 프로토타입 관련 내용을 생각했을 때 extend라는 함수는 jQuery 함수 객체, 그리고 jQuery를 통해서 생성된 객체(인스턴스)가 모두 사용이 가능하다는 의미가 됩니다. 아래와 같은 형태가 되겠죠.

 

// extend 호출 예시
jQuery.extend();

var example = new jQuery( ... );
example.extend();

 

 


 

다음으로는 if문 영역입니다. 기본적으로 extend( )는 두 개의 파라미터 obj, prop을 받는 구조입니다. 그리고 첫 번째 객체(obj)에 두 번째 객체(prop)의 프로퍼티를 복사하도록 선언되어 있죠. 하지만, 인자 값으로 obj만 들어오는 경우를 정의한 것이 이 if문 영역입니다. 

 

 

if( !prop ) {
  prop = obj;
  obj = this;
}

 

prop이 없는 경우에는 this가 기존의 obj가 되고, obj가 기존의 prop의 역할을 하게 됩니다. 즉, extend를 호출하는 객체(정확히는 new로 생성된 객체라면, new로 생성된 객체 자신을 의미합니다. 헷갈리시면 this바인딩을 다시 살펴보세요!)의 프로퍼티에 인자로 들어온 객체의 프로퍼티를 복사한다는 의미가 됩니다.

 

 


 

아래의 코드는 위에서 언급한 객체의 프로퍼티를 복사하는 과정이다. 여기서는 루프를 통해 obj 객체에 prop 객체가 가진 프로퍼티를 복사해 담는 동작이 발생합니다.

 

 for( var i in prop ){
    obj[i] = prop[i];
 }

 

단, 여기서 주의할 것은 여기서 실행되는 복사는 얕은 복사(shallow copy)라는 점 입니다. 여기서 프로퍼티가 객체(배열, 함수 객체 등)여서 참조가 발생하는 데이터일 경우에는 참조 값을 복사하게 되는 것입니다. 그렇기 때문에 복사한 프로퍼티의 값들은 한 객체에서 수정이 발생하면 다른 객체에서도 동일하게 변경 사항이 적용됩니다. 

 

이러한 현상을 방지하게 위해 깊은 복사(deep copy)로 extend를 구현하기도 하는데, 이 부분은 따로 살펴보도록 하겠습니다.