자바스크립트에서 생성자 객체는 모두 prototype라는 객체가 기본적으로 내장되어 있다.
<script>
function Person(name, company) {
this.name = name;
this.company = company;
this.getName = function() {
return this.name;
};
this.setName = function(name) {
this.name = name;
};
}
const ji = new Person("ji", "데브코스");
console.log(ji);
console.log(Person.prototype);
</script>
}
Person이라는 생성자 객체를 만들고 prototype을 출력해보면 생성자 객체는 기본적으로 빈 프로토타입 객체를 내장하고 있는것을 확인할 수 있다.
<script>
function Person(name, company) {
this.name = name;
this.company = company;
this.getName = function() {
return this.name;
};
this.setName = function(name) {
this.name = name;
};
}
const ji = new Person("ji", "데브코스");
const li = new Person("li", "데브코스");
console.log(ji);
console.log(li);
</script>
}
Person 생성자로 만들어진 ji와 li는 getName(), setName() 두 개의 함수가 쓸모없이 중복되어 생성된다.
이때 Person객체의 프로타타입으로 getName(), setName()을 만들어주면 하위 인스턴스 객체들은 name, company 속성만 생성되고 getName(), setName() 함수들은 Person의 프로토타입을 상속받아 사용할 수 있게 된다.
<script>
function Person(name, company) {
this.name = name;
this.company = company;
}
Person.prototype.getName = function() {
return this.name;
};
Person.prototype.setName = function(name) {
this.name = name;
};
const ji = new Person("ji", "데브코스");
const li = new Person("li", "데브코스");
console.log(ji);
console.log(li);
console.log(ji.getName());
console.log(li.getName());
</script>
ji와 li 인스턴스 객체는 name과 company 속성만 생성되고 getName(), setName()은 생성되지 않는다는 점에 중요하다.
getName(), setName()은 Person 생성자 함수의 프로타입에 정의 되어있고 ji와 li 인스턴스 객체는 Person의 프로토타입을 상속받아 필요할때마다 찾아서 사용하는 것이다. 이는 중복을 줄이며 메모리도 절약할 수 있다.
무작정 상위 프로토타입을 찾아가서 사용하는게 아니라 먼저 자기 자신의 프로퍼티를 검사하고 만약 있다면 자기 자신을 사용하지만 없다면 상속받은 부모 프로토타입으로가서 있다면 사용하게 되는 것이다.
자식 인스턴스 객체들이 부모 프로토타입 객체에 직접적으로 접근할 수 없을까?? __proto__로 가능하다.
그럼 prototype vs __proto__ 이 두개의 차이는 뭘까?
<script>
function Person(name, company) {
this.name = name;
this.company = company;
}
Person.prototype.getName = function() {
return this.name;
};
Person.prototype.setName = function(name) {
this.name = name;
};
const ji = new Person("ji", "데브코스");
console.log("자식 객체에서 접근 : ", ji.__proto__);
console.log("부모 객체에서 접근 : ", Person.prototype);
</script>
prototype의 속성은 부모 객체에서 자기 자신의 프로타입 객체를 가르키고 있다.
__proto__는 자식 객체에서 부모 객체의 프로토타입 객체를 가르키고 있다.
사실 자바스크립트에서는 대부분 프로토타입 구조로 만들어져있다.
우리가 자주사용하는 배열 객체만해도 우리는 이미 프로토타입을 상속받아 sort(), pop(), push(), slice(), split() 등... 함수들을 우리도 모르게 편하게 사용하고 있다고 생각하면 된다.
<script>
const array1 = [1, 2, 3];
const array2 = new Array(1, 2, 3);
console.log(Array.prototype);
console.log(array1.__proto__);
</script>
우리가 배열을 선언할때 []로 자주 선언한다. 하지만 []는 곧 new Array()랑 똑같은 모습이다. new Array()??? 어디서 많이 보던 문법이지 않는가?
그렇다 배열을 선언할때 Array라는 생성자 객체를 통해 만들고 있다는 뜻이다. 그리고 우리는 배열에 관련된 함수들을 만든적도 없는데 어떻게 사용하는거지? 라고 생각할 수 있다.
이는 Array 생성자 객체의 프로토타입에 모두 모두 정의되어있고 우리는 Array 생성자를 통해 인스턴스 배열 객체를 만들어 그저 부모 Array 생성자 함수의 프로토타입에 접근하여 사용하고 있는 것 뿐이다.