💡 JavaScript는 프로토타입 기반 언어이다.
클래스 기반 언어에서는 ‘상속’을 사용하지만 프로토타입 기반 언어에서는 어떤 객체를 원형으로 삼고 이를 복제(참조) 함으로써 상속과 비슷한 효과를 얻는다.
var instance = new Constructor();
var Person = function(name){
this._name = name;
};
Person.prototype.getName = function() {
return this._name;
};
var suzi = new Person('Suzi');
suzi.__proto__.getName(); //undefined
Person.prototype === suzi.__proto__ //true
왜 suzi.__proto__.getName();
는 undefined가 나오고
Person.prototype === suzi.__proto__
는 true가 나올까?
⇒ undefined가 나온이유 : 에러가 발생하지 않음 = 호출할 수 있는 함수이다.
실행할 수 없는 함수였다면 `TypeError`가 발생했을 것이다.
⇒ true가 나온 이유 : 왜냐하면 instance의 __proto__
가 Constructor의 prototype
프로퍼티를 참조
하므로 결국 둘은 같은 객체를 바라보기 때문이다.
var Person = function(name){
this._name = name;
};
Person.prototype.getName = function() {
return this._name;
};
var suzi = new Person('Suzi');
suzi.__proto__._name = 'SUZI__proto__'
suzi.__proto__.getName(); //'SUZI__proto__'
예상대로SUZI__proto__
가 잘 출력된다.
__proto__
를 생략하지 않으면 this는 suzi.__proto__
를 가리키지만, 이를 생략하면 suzi를 가리킵니다. suzi.__proto__
에 있는 메서드인 getName
을 실행하지만 this는 suzi를 바라보게 할 수 있게 된 것.. 도식으로 보면 다음과 같다.
var 어레이 = [4,5,1];
Array.prototype.어떤함수 = function(){
} ;
어떤함수라는 함수가 생긴것을 확인 할 수 있다.
💡 생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있게 됩니다.
💡 생성자 함수의 프로퍼티인 prototype 의 객체 내부에는 constructor라는 프로퍼티가 있습니다. 인스턴스의
__proto__
객체 내부에도 마찬가지입니다.
이 프로퍼티는 원래의 생성자함수 (자기자신)을 참조합니다.
var NewConstructor = function() {
console.log('this is new constructor!');
};
var dataTypes = [
1, //Number & false
'test', //String & false
true, //Boolean & false
{}, //NewConstructor & false(아래 동문)
[],
function(){},
/test/,
new Number(),
new String(),
new Boolean,
new Object(),
new Array(),
new Function(),
new RegExp(),
new Date(),
new Error()
];
dataTypes.forEach(function (d) {
d.constructor = NewConstructor;
console.log(d.constructor.name, '&', d instanceof NewConstructor);
});
모든 데이터가 d instanceof NewConstructor
명령에 대해 false를 반환합니다. 이로부터 constructor를 변경하더라도 참조하는 대상이 변경될 뿐 이미 만들어진 인스턴스의 원형이 바뀐다거나 데이터 타입이 변하는 것은 아님을 알 수 있습니다.
6-2-2 프로토타입 체인