프로토타입
프로토타입
const user = {
name: "Mike",
};
console.log(user.name); // Mike
객체에는 자신이 프로퍼티를 가지고 있는지 확인하는 메소드가 있다.
console.log(user.hasOwnProperty("name")); // true
console.log(user.hasOwnProperty("age")); // false
하지만 hasOwnProperty는 만든적이 없이 없다.
console.log(user); // name: "Mike"
hasOwnProperty는 만든적이 없지만 console.log(user); 에 프로토타입으로 만들어진다.
만약 hasOnwProperty가 객체 안에 있다면
const user2 = {
name: "Tom",
hasOwnProperty: function () {
console.log("ha");
},
};
user2.hasOwnProperty(); // ha
일단 객체 안에 그 프로퍼티가 있다면 그것으로 탐색을 멈춘다.
없을 경우에만 프로토타입에서 프로퍼티를 탐색한다.
프로토타입과 상속
const bmw = {
color: "red",
wheels: 4,
navigation: 1,
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()는 모두 동일할 때 proro로 해결할 수 있다.
car라는 상위 개념의 객체를 만들어서
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;
console.log(bmw); // {color: 'red', navigation: 1}
console.log(bmw.color); // "red"
console.log(bmw.wheels); // 4
car가 bmw, benz, audi의 프로토타입이 된다.
bmw, benz, audi는 car의 상속을 받는다.
상속은 계속 이어질 수 있다.
const car = {
wheels: 4,
drive() {
console.log("drive.,");
},
};
const bmw = {
color: "red",
navigation: 1,
};
bmw.__proto__ = car;
const x5 = {
color: "white",
name: "x5",
};
x5.__proto__ = bmw;
console.log(x5); // {color: 'white', name: 'x5'}
console.log(x5.navigation); // 1 / x5에서 탐색. 없으니 bmw 탐색
console.log(x5.wheels); // 4 / x5에서 탐색. 없으니 bmw 탐색. 없으니 car 탐색
위와 같이 상속이 계속 이어지는 것을 Prototype Chain 이라고 한다.
for in을 이용해서 객체 프로퍼티를 순회
for (p in x5) {
console.log(p);
} // color, name, navigation, wheels, drive
for in 을 이용해서 객체를 순회하면 프로토타입까지 포함되어 출력된다
console.log(Object.keys(x5)); // ['color', 'name']
console.log(Object.values(x5)); // ['white', 'x5']
하지만 객체 내장 메소드에서는 상속된 프로퍼티는 나오지 않음
for in을 사용하여 객체가 직접 가지고 있는 프로퍼티를 구분하는 방법
for (p in x5) {
if (x5.hasOwnProperty(p)) {
console.log("o", p);
} else {
console.log("x", p);
}
}
hasOwnProperty는 객체가 직접 가지고 있는 프로퍼티만 반환
생성자함수 이용
const car = {
wheels: 4,
drive() {
console.log("drive..");
},
};
const BMW = function (color) {
this.color = color;
};
const x5 = new BMW("red");
const z4 = new BMW("blue");
x5.__proto__ = car;
z4.__proto__ = car;
하지만 매번 proto를 사용하는 것은 비효율적
const BMW = function(color){
this.color = color;
};
BMW.prototype.wheels: 4,
BMW.prototype.drive(){
console.log("drive..");
},
const x5 = new BMW("red");
const z4 = new BMW("blue");
instance
생성자함수가 새로운 객체를 만들어 낼 때 그 객체는 생성자의 instance라고 불림
instanceof를 통해서 객체와 생성자를 비교할 수 있다.
const BMW = function(color){
this.color = color;
};
BMW.prototype.wheels: 4,
BMW.prototype.drive(){
console.log("drive..");
},
const x5 = new BMW("red");
console.log(x5 instanceof BMW); // true
생성자로 만들어진 instance 객체에는 constructor라는 프로퍼티가 존재한다.
constructor는 생성자 즉, 위에서는 BMW를 가리킨다. 따라서
const BMW = function(color){
this.color = color;
};
BMW.prototype.wheels: 4,
BMW.prototype.drive(){
console.log("drive..");
},
const x5 = new BMW("red");
console.log(x5.constructor === BMW); // true
위 예제에서
const BMW = function(color){
this.color = color;
};
BMW.prototype.wheels: 4,
BMW.prototype.drive(){
console.log("drive..");
},
const x5 = new BMW("red");
// 를
BMWo.prototype = {
wheels: 4,
drive(){
console.log("drive..");
},
};
console.log(x5.constructor === BMW); // false
처럼 prototype에 직접적으로 덮어씌워도 작동은 하지만 constructor를 잃어버린다.
따라서 prototype 프로퍼티를 객체로 한번에 추가하는 것보다 하나씩 추가해야한다.
혹은 수동으로 constructor: BMW를 직접 추가해서 문제를 해결할 수 있다.
Closuer 사용
const Audi = function (color) {
this.color = color;
return console.log(color);
};
const a6 = new Audi("red");
console.log(a6.color); // red
a6.color = "black";
console.log(a6.color); // black
이렇게 객체의 값을 아무나 바꿀 수 있는 상태이기 때문에 Closer를 이용해서 고정한다.
const Audi = function (color) {
const c = color;
this.getColor = function () {
console.log(c);
};
};
const a6 = new Audi("red");
a6.getColor(); // red
댓글남기기