객체가 특정 프로퍼티를 (직접) 가지고 있는지 확인 (
boolean
)
객체명.hasOwnProperty('확인할 프로퍼티 이름')
const user = {
name: "Mike"
}
user.name // 'Mike'
user.hasOwnProperty('name') // true
user.hasOwnProperty("age") // false
[[Prototype]]
(__proto__
) 라는 객체가 있음. 이것을 프로토 타입
이라고 함.hasOwnProperty
존재 시만든 메소드가 동작함.
일단 객체에 그 프로퍼티가
있으면 → 거기서 탐색 중지.
없을 때만 → 프로토타입에서 프로퍼티를 찾음.
예시 코드
const user = {
name: "Mike",
hasOwnProperty: function () {
console.log("haha")
}
}
user.hasOwnProperty() // 'haha'
상위 개념 객체 생성
공통된 부분들이 해당됨.
기존 객체들에서 공통 부분 지우기
[상속] 객체명.__proto__ = 상위 개념 객체명
작성
상위 개념 객체가 해당 객체의 프로토타입이 됨.
== 해당 객체는 상위 개념 객체의 상속을 받음.
‘(상속 받은) 프로퍼티 사용하는 경우’ 원리
객체명.프로퍼티
작성
객체 내부에서 프로퍼티를 찾음
찾으면 → 탐색 중지
없다면 → __proto__
(상속받은 프로퍼티 有) 확인
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
→ 문제 : 차들이 늘어나면 계속 새로운 변수로 만들어짐.
처리 방법
__proto__
로 해결 가능
// 1. 상위 개념 객체(car) 생성
const car = {
wheels: 4, // 👈 공통된 프로퍼티들
drive(){
console.log('...drive')
},
}
// 2. 공통 부분 (wheels, drive) 지움.
const bmw = {
color: "red",
navigation: 1,
}
const benz = {
color: "black",
}
const audi = {
color: "blue",
}
// 3. 상속
bmw.__proto__ = car;
benz.__proto__ = car;
audi.__proto__ = car;
// 4. [확인] (상속 받은) 프로퍼티 사용
bmw // {color: 'red', navigation: 1} 밖에 안 나옴.
bmw.color // 'red'
bmw.wheels // 4 (상속 받은 프로퍼티 사용)
상속은 계속 이어질 수 있다.
Prototype Chain
이란?
특정 객체의 프로퍼티 or 메소드에 접근 시, 객체 자신의 것뿐 아니라 __proto__
가 가리키는 링크를 따라서 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티 or 메소드에 접근 가능
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;
x5.name // 'x5'
x5.color // 'white' (이유: x5에 color가 있으니 여기까지 탐색 후, 값 주고 멈춤.)
x5.navigation // 1
원리
navigation
x5에서 찾고 없으니까
→ prototype
인 bmw
에서 탐색
→ 있으니까 멈춤.
drive()
x5
에 없고
→ bmw
로 올라가봐도 없고
→ prototype
인 car
까지 올라가서야 사용 가능
모두 나옴.
기본 예시
// Prototype Chain 예시 코드 활용
for (p in x5) {
console.log(p)
}
/*
- 결과:
'color'
'name'
'navigation'
'wheels'
'drive'
- 설명:
name, color 제외하고 프로토타입에서 정의한 프로퍼티들임. */
객체가 직접 가지고 있는지 구분하고 싶다면
→ hasOwnProperty()
활용
for (p in x5) {
if (x5.hasOwnProperty(p)){
console.log('o',p)
} else {
console.log('x',p)
}
}
/*
'o' 'color'
'o' 'name'
'x' 'navigation'
'x' 'wheels'
'x' 'drive'
*/
상속된 프로퍼티 → 안 나옴.
// Prototype Chain 예시 코드 활용
Object.keys(x5) // [ 'color', 'name' ]
Object.values(x5) // [ 'white', 'x5' ]
생성자 함수 이용 시, 비슷한 객체들을 간단히 제작 가능.
const Bmw =function(color) {
this.color = color;
this.wheels = 4;
this.drive = function(){
console.log('drive..')
}
}
const x5 = new Bmw("red")
const z4 = new Bmw("blue")
리팩토링 이유
wheels
, drive
는 동일 → 분리 가능 (매개변수로 넘긴 color
제외)
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;
/* 확인 */
x5 // Bmw {color: 'red'}
x5.wheels // 4
리팩토링 이유
prototype
이용 시, 중복 코드 줄이기 가능
(한 번 작업 시, 생성자로 만들어진 모든 객체에 일일이 작업(객체명.__proto__ = 상위 개념 객체명
)해줄 필요 無 (생성자 함수 사용 이유가 간편해서 인데))
const Bmw =function(color) {
this.color = color;
};
Bmw.prototype.wheels = 4;
Bmw.prototype.drive = function() {
console.log('drive..')
}
/*
기존의 __proto__와 모습이 다름.
이건 생성자 함수가 생성하는 객체의 __proto__를 wheels 이렇게 설정한다는 의미임.
그래서 x5.__proto__ = car;는 없어도 됨. */
// prototype에 몇 가지 더 추가
Bmw.prototype.navigation = 1;
Bmw.prototype.stop = function(){
console.log("STOP!")
}
const x5 = new Bmw("red")
const z4 = new Bmw("blue")
/* 확인 */
x5.wheels // 4
x5.drive() // drive..
x5.stop() // STOP!
instance
란?
생성자 함수가 새 객체를 만들어낼 때, 그 객체는 생성자의
instance
instanceof
란?
해당 객체가 생성자로부터 생성된 것인지 판단 후,
true
/false
반환
instance명.constructor
해당
instance 객체
의 생성자를 가리킴.
instance
객체에는 constructor
라는 프로퍼티가 존재예시 코드
z4 instanceof Bmw
/*
결과: true
설명: z4는 Bmw로 생성됨. -> Bmw의 instance임.
이렇게 하면 Bmw를 이용해서 z4를 만들었는지 알려줌. */
z4.constructor === Bmw
/*
결과: true
설명: 이렇게 생성자로 만들어진 instance 객체에는 constructor라는 프로퍼티가 존재함.
constructor는 생성자 즉, Bmw를 가리킴. -> true가 나옴.
*/
JS는 명확한
constructor
보장 x. 개발자에 의해 수정 가능.
문제
const Bmw = function(color) {
this.color = color;
};
Bmw.prototype = { // 👈
wheels: 4,
drive() {
console.log('drive..');
},
navigation: 1,
stop(){
console.log('STOP!')
}
}
const x5 = new Bmw("red")
const z4 = new Bmw("blue")
/* 확인 */
z4.constructor === Bmw // 👉 false
문제점
constructor
사라짐
해결
[방법 1] 하나씩 프로퍼티 추가 (’리팩토링 2' 처럼)
위 현상을 방지하기 위해서 prototype
을 덮어 쓰지 말고 하나씩 프로퍼티를 추가하는 것이 좋음.
[방법 2] 수동으로 명시
const Bmw = function(color) {
this.color = color;
};
Bmw.prototype = {
constructor: Bmw, // 👈 수동으로 명시
wheels: 4,
drive() {
console.log('drive..');
},
navigation: 1,
stop(){
console.log('STOP!')
}
}
const x5 = new Bmw("red")
const z4 = new Bmw("blue")
/* 확인 */
z4.constructor === Bmw // true
문제
const Bmw = function(color){
this.color = color;
}
const x5 = new Bmw("red")
x5 // Bmw {color: 'red'}
x5.color // 'red'
/*
[문제점] 색상: 마음대로 변경 가능.
(but, 아무나 색을 바꾸면 안됨.) */
x5.color = "black" // 'black'
x5.color // 'black'
해결
클로저 이용
const Bmw = function(color){
const c = color;
this.getColor = function(){
console.log(c)
}
}
const x5 = new Bmw("red")
/* 확인 */
x5.getColor();
/*
결과: red
설명: 초기 세팅한 color 값을 얻을 수만 있고 바꿀 방법 無.
color 함수는 생성될 당시의 context를 기억하는 것. */
참고