본문으로 바로가기


Prototype

자바스크립트는 C++,자바와 같은 클래스를 정의하고 이를 통해 객체를 생성하여 객체지향 프로그래밍을 하는 것과는 달리 클래스란 개념이 없다. 

대신에 객체 리터럴이나 생성자 함수로 객체를 생성하여 객체지향 프로그래밍을 지원하는데 이렇게 객체리터럴, 생성자 함수로 생성된 객체의 부모 객체가 바로 '프로토타입 객체'이다.



즉, 상속개념과 마찬가지로 자식 객체는 부모 객체가 가진 프로퍼티에 접근하거나 메소드를 상속받아서 호출하는 것이 가능하도록 해준다.


그래서 자바스크립트는 클래스 기반이 아닌 프로토타입 기반의 객체지향 프로그래밍을 지원가능하도록 해준다.

자바스크립트의 모든 객체는 객체 자신의 부모인 프로토타입 객체를 가리키는 숨겨진 프로퍼티가 있는데 이 숨겨진 프로퍼티가  prototype 프로퍼티이며 크롬브라우저에서는 __proto__란 형식으로 구현되어 있다.

여기서 구분해야될 점이 있는데 함수 객체의 기본 프로퍼티에서 서술했듯이 함수 객체 자신의 prototype 프로퍼티와숨겨진 protype 프로퍼티인 __proto__을 구분해야 한다는 점이다.



이 둘의 차이점을 알아보도록 하자.


prototype 프로퍼티(함수 객체) vs __proto__

자바스크립트는 객체를 생성하는 방법이 객체리터럴 방식과 생성자 함수를 이용한 방식이 있다.


우선 이 두가지 방식으로 객체를 생성했을 때의 규칙을 알아 볼 필요가 있다.


자바스크립트에서 모든 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 프로토타입 객체를자신의 부모 객체로 나타내주는 __proto__로 연결되어 있다.



다음의 예제 코드를 살펴보자.

생성자 함수 방식으로 객체 생성


// Jaehee 생성자 함수 정의
function Person(name) {
this.name = name;
}

// Person() 생성자 함수를 이용하여 jaehee란 객체를 생성
var jaehee = new Person('jaehee!!!');

// 프로퍼티를 알아보기 위해 dir 사용
console.dir(Person);
console.dir(jaehee);


크롬 브라우저의 콘솔창의 결과 화면을 보면  첫번째 콘솔 항목에 prototype: Person 과 두번째 콘솔 항목에 __proto__: Person을 확인할 수가 있다.


* Person에서 

prototype: Person의 prototype 프로퍼티는 함수가 생성될 때 만들어지며 constructor 프로퍼티 하나만 있는 객체를 가리킨다.

즉, 함수의 입장에서 자신과 링크된 프로토타입 객체를 가리키므로 Person.prototype과  Person()은 서로 참조하고 있다.


*jaehee에서

__proto__: Person은 객체의 입장에서 자신의 부모 객체인 프로토타입 객체를 내부의 숨겨진 링크인 __proto__로 가리키고 있으며생성자 함수를 통해 생성된 객체이므로 위에 언급했듯이 자신의 부모 객체로 나타내주는  __proto__가 Person을 가리키고 있는 것으로 보아 Person.prototype이 jaehee의 프로토타입 객체인 것이다.


결국, 자바스크립트에서 객체를 생성하는 건 생성자 함수의 역할이지만, 생성된 객체의 실제 부모 역할을 하는 건 생성된 객체 자신이 아닌 생성자의 prototype 프로퍼티가 가리키고 있는 프로토타입 객체다.




다음으로 객체 리터럴 방식으로 객체를 생성해 보자.


// 객체 리터럴 방식으로 foo 객체 생성
var foo = {
name : 'jaehee',
gender : 'man',
year : 2015
}


크롬 브라우저의 개발자 도구에서 객체를 출력해보면 __proto__:  Object 인 것을 확인할 수 있다.

이렇게 foo객체의 프로토타입객체(__proto__)은 Object(실제로 Object.prototype)이다.



위의 출력 결과를 보면 알겠지만, 객체 리터럴 방식과 생성자 함수 방식의 차이가 프로토타입 객체(__proto__)에서 나타나고 있음을 알 수 있다. 예제 코드 출력상에서 객체리터럴 방식의 경우는 자신의 프로토타입 객체가 Object, 생성자 함수의 경우는  Person으로

서로 다름을 확인할 수 있다. 이렇게 차이가 발생하는 이유는 자바스크립트가 객체를 생성하는 규칙때문인 것이다.

자바스크립트 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다.

객체 리터럴 방식에서는 객체를 생성하는 생성자 함수는 빌트인 Object()이며, 생성자 함수 방식의 경우는 생성자 함수 자체인 것이다.

그렇게 때문에 예제 코드에서 객체 생성 방법이 다르기 때문에 서로 다른 프로토타입 객체를 참조하고 있는 것이다.


자바스크립트에서는 일반 함수와 생성자 함수의 차이

일반함수와 생성자 함수는 별도의 차이가 없지만 new연산자를 붙여서 함수를 호출하면 생성자 함수로서 동작하는 것이다. 

객체 생성을 목적으로 작성한 생성자 함수를 new 없이 호출하거나 일반 함수 생성을 목적으로 작성한 코드에 new를 붙여서 호출할 경우 코드에서 오류가 발생할 수가 있다.

그 이유는 생성자 함수 호출과 일반 함수를 호출할 때 this 바인딩 방식이 달라지기 때문이다.

일반 함수 호출의 경우는 this가 window 전역객체에 바인딩되는 반면에, 생성자 함수 호출에서 this는 new 생성자함수()를 통해 생성되는 객체에 바인딩되기 때문이다.

그래서 자바스크립트에서는 생성자 함수 작성시에 생성자 함수로서 코드가 작성됐음을 강조하기 위해서 함수명의 첫글자를 대문자로 사용하기를 권장하고 있다.



Jaehee's WebClub