유블로그

자바스크립트 프로토타입 체이닝 본문

JavaScript & jQuery

자바스크립트 프로토타입 체이닝

yujeong kang 2021. 6. 18. 23:32

자바스크립트는 프로토타입 기반의 객체지향 프로그래밍을 지원한다.

 

자바스크립트는 클래스 개념이 없으므로 객체 리터럴이나 생성자 함수로 객체를 생성하는데, 이 때 생성된 객체의 부모 객체가 프로토타입 객체이다.

상속과 비슷하게 자식 객체는 부모 객체가 가진 프로퍼티 접근, 메서드를 상속받아 호출이 가능하다.

전 글의 그림을 들고와서 보면

yj 객체가 부모 객체의 프로토타입 객체를 [[Prototype]] 객체로 링크를 한다(참조링크형태)

 

결국 생성된 객체의 실제 부모 역할을 하는 건, 생성자 자신(Person) 이 아닌, 생성자의 prototype 프로퍼티가 가리키는 prototype 객체인 것이다.

 


프로토타입 체이닝

프로토타입 체이닝 덕분에 객체는 자신의 프로퍼티 뿐 아니라 부모 역할을 하는 프로토타입 객체의 프로퍼티도 접근할 수 있다.

 

프로토타입 체이닝이란 객체에 접근하려는 프로퍼티 또는 메서드가 없을 때 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티를 차례대로 검색하는 것이다.

 

자신에게 프로퍼티 또는 메서드가 없으면 [[Prototype]] 링크를 따라 부모에게 프로퍼티나 메서드가 있는 지 확인한다.

위 그림에서 yj 객체가 프로토타입을 따라 Person.prototype에서 메서드를 탐색했는데 없다면, Person 의 프로토타입인 Object로 또 링크를 따라간다. 

Object.prototype은 프로토타입 체이닝의 종점이다.

 

 

기본데이터 타입과 프로토타입에도 프로퍼티나 메서드를 추가하는 것이 가능하다.

String.prototype.testMethod = function () {
	console.log('this is a test');
};

var str = 'test!';
str.testMethod();
function Person(name) {
	this.name = name;
}

var yj = new Person('yj');
yj.hello();	// 여기선 아직 hello 메서드가 없어 에러남

Person.prototype.hello = function() {
	console.log("hello");
};

yj.hello();	// 부모 프로토타입에 hello 메서드가 있어 에러나지 않음

 

프로토타입 메서드에서 this 는 어디에 바인딩될까?

function Person(name) {
	this.name = name;
}

Person.prototype.getName = function() {
	console.log(this.name);
};

var yj = new Person('yj');
yj.getName();	// yj

Person.prototype.name = 'yj2';
Person.prototype.getName();	// yj2

 

yj.getName() 에서는 호출한 객체가 yj 이므로 this가 yj 객체에 바인딩

Person.prototype.getName()에서는 호출한 객체가 Person.prototype이므로 this가 Person.prototype 에 바인딩

 


디폴트 프로토타입을 다른 객체로 변경하면?

function Person(name) {
	this.name = name;
}
console.log(Person.prototype);	// Person(name)

var yj = new Person('yj');
console.log(yj.country);	// undefined

Person.prototype = {
	country: 'korea';
};
console.log(Person.prototype.constructor);	// Object()

var yj2 = new Person('yj2');
console.log(yj.country);	// undefined
console.log(yj2.country);	// korea
console.log(yj.constructor);	// Person(name)
console.log(yj2.constructor);	// Object()	: Object.prototype 으로 체이닝 발생


프로퍼티를 읽거나 메서드 실행 때만 프로토타입 체이닝이 동작한다.

프로퍼티 쓰는 경우엔 일어나지 않고 단지 동적으로 프로퍼티를 추가한다.

function Person(name) {
	this.name = name;
}
Person.prototype.country = 'Korea';

var yj = new Person('yj');
var yj2 = new Person('yj2');
console.log(yj.country);	// Korea
console.log(yj2.country);	// Korea

yj.country = 'USA';
console.log(yj.country);	// USA
console.log(yj2.country);	// Korea

 

 

출처: 송형주, 고현준, 인사이트 자바스크립트, 한빛미디어(2020)