javascript는 프로토타입 기반 언어이다.
프로토타입은 이미 정의된 객체를 복사하여 생성되는 또 다른 객체라고 볼 수 있다.
function Animal(){}
Animal이라는 함수를 정의했다. 이 함수 내부에는 그 어떠한 정보도 가지고 있지 않다.
function Animal(){}
// 고양이 프로토타입 생성
const Cat = new Animal();
// 개 프로토타입 생성
const Dog = new Animal();
Cat과 Dog는 Animal함수를 복사하여 생성된 프로토타입이다.
그림으로 그린다면 다음과 같이 나타난다.
Dog와 Cat은 각자 가리키는 대상의 주소값이 다르다.
동등 비교 연산자를 이용하면 결과값은 다음과 같이 나온다.
...
console.log(Cat === Dog); // false
만약 Animal 함수에 직접 무언가를 추가하면 어떻게 될까?
Cat과 Dog는 이미 Animal 함수를 복사하고 새로 생성하여 참조하고 있다.
그럼, Cat과 Dog가 참조하고 있는 대상도 바뀔까?
...
Animal.prototype.howling = "끼에엑";
console.log("Dog :", Dog.howling); // Dog : 끼에엑
console.log("Cat :", Cat.howling); // Cat : 끼에엑
둘 다 끼에엑이라고 출력된다.
지금까지 코드를 통해 알 수 있는 점은
1. 객체를 복사하여 생성된 프로토타입은 서로 주소값이 다르다. (또 다른 새로운 객체라는 의미)
2. 프로토타입에 멤버를 추가하고 값을 할당하면 프로토타입을 참조하는 객체도 변한다.
이렇게 두 가지가 되겠다.
그렇다면 프로토타입을 참조하는 객체의 멤버값을 바꾸면 프로토타입의 멤버값도 변할까?
아래 코드를 추가하고 실행시켜보자.
...
Dog.howling = "멍멍";
console.log("Animal :", Animal.prototype.howling);
console.log("Dog :", Dog.howling);
console.log("Cat :", Cat.howling);
이번엔 Dog에 howling 멤버를 추가하고 값을 부여해봤다.
Cat은 아무런 값을 부여하지 않았다.
실행결과
Animal : 끼에엑
Dog : 멍멍
Cat : 끼에엑
Dog의 멤버값은 변경된 상태로 나왔으나, Animal과 Cat은 변경이 되지 않았다.
즉, 특정 객체의 멤버값을 변경하면,
변경된 객체만 영향을 받고 나머지는 영향을 받지 않는다.
그렇다면 프로토타입에 멤버를 생성하면 다른 객체의 멤버도 바뀔까?
다음 코드를 추가하고 실행시켜보자.
...
Dog.age = 12;
console.log("Animal :", Animal.prototype.age);
console.log("Dog :", Dog.age);
console.log("Cat :", Cat.age);
실행결과
Animal : undefined
Dog : 12
Cat : undefined
프로토타입에 멤버를 생성하면 그 프로토타입만 영향을 받는 것을 볼 수 있다.
위에서 Dog에 age를 추가했는데,
만약 Animal에 age를 추가하고 값을 할당한다면 Dog의 age값이 바뀔까?
...
Animal.prototype.age = 15;
console.log("Animal :", Animal.prototype.age);
console.log("Dog :", Dog.age);
console.log("Cat :", Cat.age);
실행결과
Animal : 15
Dog : 12
Cat : 15
객체에 멤버를 직접추가하면 프로토타입도 멤버가 추가되기 때문에
Cat의 age는 가 15로 출력된 것을 확인할 수 있다.
그러나 Dog의 age는 변하지 않고 초기값 그대로 출력됐다.
그렇다면 멤버에 값대신 함수를 넣는다면 어떻게 될까?
...
Animal.prototype.getType = () =>{
return "동물";
}
console.log("Dog :", Dog.getType());
console.log("Cat :", Cat.getType());
Dog : 동물
Cat : 동물
예상대로 똑같이 생성된다.
위 네 개의 코드를 보고 알 수 있는 점은
1. 프로토타입의 멤버를 생성하면 해당 프로토타입 내 멤버만 생성되고 나머지는 영향을 주지 않는다.
2. 프로토타입에 멤버를 생성하고 객체에도 동일한 멤버를 생성하고 값을 할당하면, 이미 프로토타입에 생성되어 있는 멤버값은 변하지 않는다.
최종 코드는 다음과 같다.
function Animal(){}
// 고양이 프로토타입 생성
const Cat = new Animal();
// 개 프로토타입 생성
const Dog = new Animal();
console.log(Cat == Dog);
Animal.prototype.howling = "끼에엑";
console.log("Dog :", Dog.howling);
console.log("Cat :", Cat.howling);
Dog.howling = "멍멍";
console.log("Animal :", Animal.prototype.howling);
console.log("Dog :", Dog.howling);
console.log("Cat :", Cat.howling);
Dog.age = 12;
console.log("Animal :", Animal.prototype.age);
console.log("Dog :", Dog.age);
console.log("Cat :", Cat.age);
Animal.prototype.age = 15;
console.log("Animal :", Animal.prototype.age);
console.log("Dog :", Dog.age);
console.log("Cat :", Cat.age);
Animal.prototype.getType = () =>{
return "동물";
}
console.log("Dog :", Dog.getType());
console.log("Cat :", Cat.getType());
console.log(Dog);
지금까지의 내용을 정리하면 프로토타입의 특성은 다음 네 가지가 되겠다.
1. 원형 객체를 복사하여 생성된 프로토타입은 서로 주소값이 다르다. (또 다른 새로운 객체라는 의미)
2. 원형 객체에 멤버를 추가하고 값을 할당하면 프로토타입도 객체의 멤버를 따라가게 된다.
3. 프로토타입의 멤버를 생성하면 해당 프로토타입 내 멤버만 생성되고 나머지는 영향을 주지 않는다.
4. 프로토타입에 멤버를 생성하고 원형 객체에도 동일한 멤버를 생성하고 값을 할당하면, 이미 프로토타입에 생성되어 있는 멤버값은 변하지 않는다.