메서드 이름 | 설명 |
---|---|
Object.assign() | 하나 이상의 객체를 결합하여 지정한 객체에 복사한다. |
Object.create() | 지정한 속성을 갖는 새로운 객체를 생성한다. |
- target: 대상객체 - sources: 복사할 원본
sources...로 지정된 객체의 멤버를 target에 복사되어 결합 후의 객체를 반환된다. (target에도 영향을 미친다)
동일 명칭의 프로퍼티는 나중에 정의된 값으로 덮어 쓰여진다.
let pet1 = {
type: 'cat',
name: 'coco',
description: {
birth: '2020-08-17'
}
};
let pet2 = {
name: 'chuchu',
color: 'black',
description: {
food: 'feed'
}
};
let pet3 = {
weight: 5,
age: 2
};
Object.assign(pet1, pet2, pet3);
/*
pet1 = {
age: 2,
color: 'black',
description: {
food: 'feed'
}
name: 'chuchu',
type: 'cat',
weight: 5,
}
*/
앞서 설명했듯이 target에 pet1이 지정되어 있기때문에 target객체인 pet1에 변화가 생겼다.
재귀적인 결합을 지원하지 않기때문에 description이 통째로 교체된다(birth → food)는 점에 주의한다.
만약, sources객체들에 영향을 끼치고 싶지 않다면, 다음과 같이 target에 {}를 지정해주면 빈 객체에 sources객체를 결합한 값들을 반환한다.
Object.assign({}, pet1, pet2, pet3);
// 1 - 객체 리터럴
const obj = { a: 1, b: 2, b: 3};
// 2 - new 연산자 이용
const obj2 = new Object();
// 3 - Object.create()이용
1, 2의 방법으로 생성된 객체는 Object의 인스턴스로써 Object의 기본 메서드를 계승하고 있다. (toString, valueOf등) Object.create메서드의 proto 인수에 null을 전달하면 Object의 프로토타입을 계승하지 않는 완전한 빈 객체를 만들 수 있다. (null이 전달되어 만들어진 객체는 toString, valueOf등의 메서드를 사용할 수 없다.)
// Object 프로토타입이 계승되지 않은 완전히 빈 객체 생성
Object.create(null)
Object.create로 빈 객체를 만들 수도 있지만 다양한 속성을 이용하여 커스텀도 가능하다. Object.create의 props에는 다음과 같은 프로퍼티 속성을 가질 수 있다.
프로퍼티 속성 | 개요 | 기본값 |
---|---|---|
configurable | 프로퍼티를 변경할 수 있는지 정하는 속성 | false |
enumerable | 프로퍼티가 열거 가능한지 정하는 속성 | false |
value | 프로퍼티의 값 저장 | - |
writable | 프로퍼티에 값을 저장할 수 있는지 정하는 속성 | false |
get | - | |
set | - |
// Object.create를 이용하여 Object 프로토타입을 계승한 새로운 객체 생성
let coffee = Object.create(Object.prototype, {
name: {
value: 'Americano',
writable: true,
configurable: true,
enumerable: true,
},
price: {
value: 4100,
writable: true,
configurable: true,
enumerable: true,
},
get: {
value: function() {
return this.name;
}
},
set: {
value: function(name) {
this.name = name
}
}
})
console.log(coffee.name) // 'Americano'
console.log(coffee.price) // 4100
console.log(coffee.get()) // 'Americano'
coffee.set('cafe latte')
console.log(coffee.get()) // 'cafe latte'
위의 예제에서 configurable의 속성값을 true로 설정하였기 때문에 coffee.set()으로 name의 value값을 변경할 수 있었다. 위의 속성을 적절하게 사용하면 Object.create로 생성된 객체를 수정/복사 하여 활용할 수 있을 것이다.
Object.create를 다루는 자료들을 찾아보면 new Constructor()와 비교하는 글이 꽤 많았다. Object.create를 이용하는 것과 new키워드를 이용해 객체를 생성하는 것과의 공통점과 차이점은 뭘까?
function Coffee() {
this.name = 'Americano';
}
Coffee.prototype.price = 4100;
let drink1 = new Coffee(); // 생성자를 이용한 객체 생성
let drink2 = Object.create(Coffee.prototype);
console.log(drink1.name); // 'Americano'
console.log(drink1.price); // 4100
console.log(drink2.name); // undefined
console.log(drink2.price); // 4100
위의 예제를 보면 drink1.price와 drink2.price가 정상적으로 출력되었으며 price 프로토타입이 정상적으로 계승되었다는 것은 확인할 수 있다. 문제는 Coffee함수 내부에 선언된 name프로퍼티에 접근할 때 발생하였다.
생성자를 이용하여 선언한 drink1는 문제없이 name프로퍼티에 접근이 가능했지만 Object.create로 선언한 drink2변수는 name프로퍼티에 접근 시 undefined를 출력하였다. 즉 Object.create는 Constructor의 this.name에 접근할 수 없다.
- 왜 접근할 수 없는데?
Coffee함수의 프로토타입을 상속받는 생성자 객체 drink1를 만들면, Coffee는 drink1 객체의 this를 해당 객체에 바인딩 시킨다. Object.create로 만든 drink2는 단순히 Coffee함수의 프로토타입을 상속받아 객체를 생성했을 뿐이다. 따라서 프로토타입을 사용할 순 있지만, 생성자 함수의 내부 프로퍼티에 접근 할 수 없다.
공통점
차이점