프로토타입(prototype)
아래의 코드에서 user객체의 name 속성의 유무를 확인할 수 있는 hasOwnProperty라는 함수를 사용했습니다. 이 함수는 어디서 온 것일까요?
const user = {
name : 'Mike'
}
console.log(user.name);
console.log(user.hasOwnProperty('name'));
console.log(user.hasOwnProperty('age'));
자바스크립트의 모든 객체는 프로토타입(prototype) 이라는 객체를 가지고 있습니다.
모든 객체는 그들의 프로토타입으로부터 프로퍼티와 메소드를 상속받습니다.
이처럼 자바스크립트의 모든 객체는 최소한 하나 이상의 다른 객체로부터 상속을 받으며,
이때 상속되는 정보를 제공하는 객체를 프로토타입(prototype)이라고 합니다.
상속(inheritnace)
상속(inheritance)이란 새로운 클래스에서 기존 클래스의 모든 프로퍼티와 메소드를
사용할 수 있는 것을 의미합니다.
상속을 통해 새로운 프로그램의 요구에 맞게 기존 클래스를 수정하여 재사용할 수 있습니다.
또한, 클래스 간의 종속관계를 형성함으로써 객체의 관계를 조직화 할 수 있는 장점이 있습니다.
따라서 이러한 상속은 추상화,캡슐화와 더불어 객체지향프로그래밍을 구성하는 중요한 특징 중 하나가 됩니다.
다음 코드를 보겠습니다.
const bmw = {
color : "red",
navigation : 1,
wheels : 4,
drive() {
console.log("drive..");
}
}
const benz = {
color : "black",
wheels : 4,
drive() {
console.log("drive..");
}
}
const audi = {
color : "blue",
wheels : 4,
drive() {
console.log("drive..");
}
}
위의 코드에서 wheels와 drive함수가 모든 객체에 공통입니다. 따라서 중복을
제거하기 위해서 상속을 이용합니다. 상속을 이용하면 아래의코드가 됩니다.
const car = {
wheels : 4,
drive() {
console.log("drive..");
}
}
const bmw = {
color : "red",
navigation : 1,
}
const benz = {
color : "black",
}
const audi = {
color : "blue",
}
bmw.__proto__ = car;
benz.__proto__ = car;
audi.__proto__ = car;
위의코드 마지막줄을 보면 car가 bmw, benz, audi의 prototype이 되는 것을 의미합니다.
이 말은 즉, bmw, benz, audi가 car의 상속을 받는것을 뜻합니다.
bmw.wheels를 하게 되면 먼저 bmw 객체 내에서 먼저 프로퍼티를 찾다가 찾지 못하면
__proto__객체에서 탐색을 하여 프로퍼티를 찾으면 그 프로퍼티를 이용합니다.
즉 위의 코드에서 아래의 코드를 추가해보겠습니다.
const x5={
color:"white",
name:"x5",
};
x5.__proto__=bmw;
console.log(x5.color);
console.log(x5.navigation);
상속은 이어지기 때문에 x5.color;을 하게되면 x5 객채 내에서 color프로퍼티를 먼저 찾게 되지만,
x5.navigation을 하게 되면 x5의 프로토타입인 bmw객체로가서 프로퍼티를 찾아 사용합니다.
결과입니다
위의 상속관계를 이미지로 보겠습니다.
만약 x5.drive()을 하게 되면 x5객체 내에서 drive메소드를 찾다가 찾지 못하고
프로토타입인 bmw로 가서 메소드를 찾습니다. 그러나 bmw에서도 찾지못하고
결국 car 프로토타입까지 도달하여 해당 메소드를 찾아 실행합니다.
이런 것을 Prototype Chain 이라고 합니다.
for in문을 이용하여 객체 프로퍼티들을 순회해 보겠습니다.
for(p in x5)
{
console.log(p);
}
그럼 keys()나 values()를 함수를 사용해보면 어떻게 될까요?
console.log(Object.keys(x5));
console.log(Object.values(x5));
아래와 같이 상속된 프로퍼티들은 나오지 않습니다. 따라서 잘 구분해서 사용해야합니다. 만약에
for in문에서 구분하고 싶다면 hasOwnProperty()를 사용하면 됩니다.
결과도 마찬가지로 직접 가진 프로퍼티만 반환합니다. 즉, 아래와 같습니다.
생성자 함수에 property 적용
이번에는 생성자 함수에서 property를 적용해보겠습니다.
const car = {
wheels:4,
drive(){
console.log("drive..");
},
};
const Bmw = function(color){
this.color=color;
}
const x5 = new Bmw("red");
const x6 = new Bmw("blue");
x5.__proto__ = car;
x6.__proto__ = car;
console.log(x5.wheels); //4
위의코드는 더 간편하게 작성할 수 있습니다.
아래와 같이 prototype을 사용하여 __proto__ 문법의 의미와 동일하게 작성할 수 있습니다.
이렇게 되면 객체를 생성할 때마다 __proto__를 해주지 않아도 되는 편리함이 있습니다.
/*
const car = {
wheels:4,
drive(){
console.log("drive..");
},
};*/
const Bmw = function(color){
this.color=color;
}
Bmw.prototype.wheels=4;
Bmw.prototype.drive=function(){
console.log("drive..");
}
const x5 = new Bmw("red");
const x6 = new Bmw("blue");
//x5.__proto__ = car;
//x6.__proto__ = car;
console.log(x5.wheels); //4
위와 같이 생성자 함수를 통해 만들어진 객체를 인스턴스라고합니다.
instanceof와 .constructor를 통해 타입을 확인할 수 있습니다.
console.log(x5 instanceof Bmw);
console.log(x6.constructor===Bmw);
만약 위의 코드에서 더 간편하게 이렇게 작성해보면 어떨까?
Bmw.prototype ={
wheels:4,
drive(){
console.log("drive..");
},
navigation:1,
stop(){
console.log("stop...");
},
};
이렇게 작성할 수는 있습니다. 하지만 constructor 함수를 사용하면 false가 나오게됩니다!
이런 현상을 방지하기 위해서 프로토타입을 덮어쓰지말고 하나씩 적는 것이 좋습니다.
혹은 위의 코드에서 중괄호안에
constructor : Bmw, 를 추가해주어도 됩니다.
위에서 보시다시피 자바스크립트에서는 명확한 constructor을 보장하지는 않습니다.
개발자에 의해서 언제든지 수정될 수 있음을 염두해 두셔야합니다!.
코드한개를 더 보겠습니다.
const Bmw = function(color){
this.color = color;
};
const x5 = new Bmw("red");
console.log(x5);
위의 코드에서 x5의 color은 언제든지 바꿀 수 있습니다.
만약 색상이 변경되지 않도록 하고 싶으면 closure(클로저)를 사용합니다.
클로저를 사용해 다시 코드를 작성해보면
const Bmw = function(color){
const c =color;
this.getColor=function(){
console.log(c);
}
};
const x5 = new Bmw("red");
x5.getColor();
아래와같이 작성되고 색상이 변경지 않습니다.
color는 생성될 당시에 색상을 기억합니다.
const Bmw = function(color){
const c =color;
this.getColor=function(){
console.log(c);
}
};
const x5 = new Bmw("red");
x5.color = "blue";
x5.getColor(); // "red"
'프론트엔드 > javascript' 카테고리의 다른 글
자바스크립트 - 프로미스(Promise) (0) | 2023.04.11 |
---|---|
자바스크립트 - 클래스(Class) (0) | 2023.04.10 |
자바스크립트 - call, apply, bind (0) | 2023.04.09 |
자바스크립트 - setTimeout/setInterval (0) | 2023.04.09 |
자바스크립트 클로저(Closure) (0) | 2023.04.09 |