Hi, There!
안녕하세요, 바오밥입니다.
목차
- 개요
- 본문
- Reference
개요
자바스크립트 객체의 프로토타입에 대해서 알아보도록 하겠습니다.
본문
프로토타입
아래 user 객체는 name 프로퍼티만 정의한 상태입니다.
그런데, 정의하지 않은 hasOwnProperty는 어떻게 사용할 수 있는 걸까요 ?
바로 프로토타입 덕분입니다.
const user = {
"name": "Mike",
}
console.log(user.name) // "Mike"
console.log(user.hasOwnProperty('name')) // true
console.log(user.hasOwnProperty('age')) // false
user 객체 안에 있는 proto (프로토타입) 객체가 이를 지원합니다.
프로토타입 객체는 선언되어 있는 객체에 없는 프로퍼티를 호출했을 때 실행됩니다.
따라서 user 객체 안에 hasOwnProperty 메서드를 정의한다면 프로토타입의 메서드가 아닌 객체에 직접 정의한 메서드가 실행됩니다.
const user = {
"name": "Mike",
"hasOwnProperty": function() {
console.log("test")
}
}
console.log(user.name) // "Mike"
console.log(user.hasOwnProperty()) // test, undefined
console.log(user.hasOwnProperty()) // test, undefined 가 출력됩니다.
이러한 prototype 기능을 이용하여 상속을 구현할 수 있습니다.
상기해 놓은 내용대로 정의된 메서드나 프로퍼티가 없을 경우 프로토타입 객체로 이동하여 메서드와 프로퍼티를 조회합니다.
따라서 bmw와 benz의 공통적인 특성인 바퀴 4개를 car라는 객체로 묶고, 이를 bmw 및 benz 객체의 프로토타입에 집어넣으면 car의 프로퍼티를 bmw와 benz가 상속 받는 꼴이 됩니다.
const car = {
wheels: 4
}
const bmw = {
color: "red",
navigation: 1
}
const benz = {
color: "black"
}
bmw.__proto__ = car;
benz.__proto__ = car;
프로토타입은 여러 번 상속하는 것도 가능합니다.
const car = {
wheels: 4
}
const bmw = {
color: "red",
navigation: 1
}
const benz = {
color: "black"
}
const x5 = {
modelVersion: "x5"
}
bmw.__proto__ = car;
benz.__proto__ = car;
x5.__proto__ = bmw;
console.log(x5.wheels) // 4, car를 상속한 bmw를 상속하였기 때문에 4가 출력됨
프로토 타입은 숨김 프로퍼티이기 때문에 Object.keys 또는 Object.values 메서드로 조회가 불가능합니다.
const car = {
wheels: 4
}
const bmw = {
color: "red",
navigation: 1
}
const benz = {
color: "black"
}
const x5 = {
modelVersion: "x5"
}
bmw.__proto__ = car;
benz.__proto__ = car;
x5.__proto__ = bmw;
console.log(x5, Object.keys(x5), Object.values(x5))
만약 프로퍼티의 상속 여부를 확인하고 싶은 경우 for문과 hasOwnProperty를 사용해야 합니다.
const car = {
wheels: 4
}
const bmw = {
color: "red",
navigation: 1
}
const benz = {
color: "black"
}
const x5 = {
modelVersion: "x5"
}
bmw.__proto__ = car;
benz.__proto__ = car;
x5.__proto__ = bmw;
for (p in x5) {
if (x5.hasOwnProperty(p)) {
console.log('객체 프로퍼티 : ', p)
} else {
console.log('상속 프로퍼티 : ', p)
}
}
객체를 정의하지 않고 프로토타입에 바로 프로퍼티를 매핑할 수 있습니다.
덕분에 생성자 함수에도 프로토타입을 매핑해 놓을 수 있습니다.
이 특성을 이용하여 중복된 작업을 효율적으로 줄여줍니다.
const Bmw = function(color) {
this.color = color;
}
Bmw.prototype.wheels = 4; // 프로토타입에 바로 매핑할 수 있습니다.
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
console.log(x5.wheels) // 4
instanceof 메서드를 이용하면 객체가 인스턴스로 포함되어 있는 지 불린형으로 반환됩니다.
하기 코드 기준으로 z4가 Bmw 생성자 함수에 인스턴스인 경우 true를 반환합니다.
const Bmw = function(color) {
this.color = color;
}
Bmw.prototype.wheels = 4;
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
console.log(z4 instanceof Bmw) // true
또는 객체의 constructor 프로퍼티를 이용하여 생성자 함수를 찾을 수 있습니다.
const Bmw = function(color) {
this.color = color;
}
Bmw.prototype.wheels = 4;
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
console.log(z4.constructor === Bmw) // true
생성자 함수에 추가 할 프로토타입이 여러 개인 경우 json 형식으로 추가할 수 있습니다.
그러나 생성자 함수를 비교할 때 false를 반환합니다.
(이러한 특성 때문에 가급적 하나로 묶지 말고 개별로 추가하는 것을 권장합니다.)
단, 인스턴스에 속해있는 지 판단 여부를 확인 할 수는 있습니다.
const Bmw = function(color) {
this.color = color;
}
Bmw.prototype = {
wheels: 4,
drive() {
console.log("drive!!")
},
navigation: 1
};
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
console.log(z4.constructor === Bmw) // false
console.log(z4 instanceof Bmw) // true
json 형태로 묶어서 추가하고 싶은 경우 constructor 프로퍼티를 수동으로 넣어주는 방법도 있습니다.
const Bmw = function(color) {
this.color = color;
}
Bmw.prototype = {
constructor: Bmw,
wheels: 4,
drive() {
console.log("drive!!")
},
navigation: 1
};
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
console.log(z4.constructor === Bmw) // true
console.log(z4 instanceof Bmw) // true
상속 받은 인스턴스를 통해서 값을 쉽게 변경할 수 있습니다.
그러나, 이는 의도치 않은 사람이 해당 값을 변경할 수 있게 해주기 때문에 보안성 측면에서 전혀 도움이 되지 않습니다.
const Bmw = function(color) {
this.color = color;
}
const x5 = new Bmw("red");
x5.color = "black" // red -> black 변경
console.log(x5.color) // black
이럴 때는 이전에 정리했던 클로저(https://baobab.live/113)를 이용해야 합니다.
color 값은 오직 생성할 때 입력된 컨텍스트로만 출력됩니다.
const Bmw = function(color) {
const c = color;
this.getColor = function() { //
console.log(c);
}
}
const x5 = new Bmw("red");
x5.color = "black"
x5.getColor(); // red
Reference
'Tech > [Lang] JS & TS' 카테고리의 다른 글
promise에 대해서 (0) | 2021.10.12 |
---|---|
클래스 (0) | 2021.10.07 |
함수 호출 메서드 (call, apply, bind) (0) | 2021.09.27 |
스케쥴링 메서드 (setTimeout, setInterval) (0) | 2021.09.24 |
클로저와 어휘적 환경 (0) | 2021.09.23 |