본문 바로가기

Programming/Javascript

10. Javascript 프로토타입 체이닝 (2) - 리터럴 객체의 프로토타입 체이닝

javascript logo image

 

명시적으로 생성자 함수를 사용하지 않고, 객체 리터럴 방식으로 생성한 객체의 경우 생성자 함수는 무엇일까요? 다룬 지 오래되어 잊어버리셨을 수도 있겠지만... 객체 리터럴 방식으로 생성된 객체의 생성자 함수는 Object( )입니다. 이는 가장 기본적인 원칙이므로 잊지 말고 다시 한번 상기하도록 합시다. 

 

Object( )라는 생성자 함수를 우리가 직접적으로 다룰 일은 많지는 않지만 이 역시 함수 객체의 한 종류입니다. 그렇다면 이 Object( ) 역시 prototype이라는 속성을 갖고 있겠죠? 여기서부터 생성자 함수에서 다루었던 내용을 그대로 적용시켜 봅시다. 객체 리터럴을 통해 생성한 객체는 어떤 [[Prototype]]을 갖게 될까요? 다름 아닌 Object.prototype을 가리키게 됩니다. 여기까지는 배웠던 내용의 반복입니다. 

 

 

프로토타입 체이닝

객체 리터럴 방식으로 생성한 객체를 예로 살펴보겠습니다. 다음 객체는 프로퍼티와 메서드를 모두 가지도록 선언하고 있습니다. rapName 프로퍼티와 이를 출력하는 printRapName 메서드가 있다고 가정해 봅시다. 

 

var rapper = {
    rapName : "Dynamic Duo",
    printRapName : function(){
        console.log(this.rapName);
    } 
};

rapper.printRapName();
console.log(rapper.hasOwnProperty('rapName'));
rapper.printLableName();   // TypeError 발생

 

위의 예시에서 중요한 부분은 rapper.hasOwnProperty 입니다. hasOwnProperty라는 메서드는 이 객체의 어디에도 선언되어 있지 않은 메서드입니다. 하지만 해당 코드를 실행하였을 때, true라는 값이 정상적으로 출력됩니다. 한편으로는 rapper.printLableName이라는 메서드를 임의로 작성해 실행하였을 때는 타입 에러가 발생합니다. 

 

여기서 rapper.hasOwnProperty가 정상적으로 실행된 것을 설명하기 위해, 프로토타입 체이닝이라는 개념을 사용해야 합니다. 프로토타입 체이닝은, 특정 객체가 가진 프로퍼티 또는 메서드에 접근을 시도할 때 해당 객체에 접근을 시도한 프로퍼티 또는 메서드가 없을 경우 - 해당 객체의 [[Prototype]] 링크를 따라 해당 프로토타입 객체의 프로퍼티를 차례대로 검색하는 것을 의미합니다. 

 

위의 예제 케이스를 통해 설명해 볼까요? console.log(rapper.hasOwnProperty('rapName')); 라는 라인에서 rapper.hasOwnProperty라는 메서드를 실행했습니다. 이 경우, 우선 rapper라는 객체 안에서 해당 메서드가 있는지를 검색합니다. 하지만 우리가 잘 알다시피 이런 메서드는 rapper 객체 안에 선언되어 있지 않습니다. 그러면 이 경우, 프로토타입 체이닝 원칙에 따라 rapper객체의 [[Prototype]] 링크를 따라 부모 객체를 찾아갑니다. 

 

rapper는 객체 리터럴 방식으로 선언된 객체이므로, 부모 객체에 해당하는 생성자 함수는 Object( )였습니다. 그럼 이제 Object의 프로토타입 객체 내에 현재 찾고 있는 메서드 hasOwnProperty 메서드가 있는지 검색하게 됩니다. 다행히, Object 안에는 표준 메서드로서 hasOwnProperty 메서드가 정의되어 있습니다. 이는 스트링 타입 인자로 넘긴 프로퍼티가 해당 객체에 존재하는지를 불린 타입으로 리턴해주는 메서드입니다. (물론 Object.prototype내에 선언된 표준 API는 이뿐만 아니라 toString( )등 다양한 메서드들이 있습니다)

 

위 예제의 프로토타입 체이닝 구조 요약

 

 

위와 같은 구조의 원리로 인해, 임의로 선언한 printLableName( ) 같은 메서드는 호출이 불가능했고, hasOwnProperty( )는 정상적으로 출력된 것입니다. 부모-자녀간의 상속과 같은 간단한 개념일 수 있지만, 프로토타입의 구조를 이해하는 것이 중요합니다.