2장 값을 잘다루기 - chhw130/Front-Basic-Deep-Dive GitHub Wiki
모든 객체는 특정 속성을 찾기위해 프로토타입 체이닝이 이뤄지고 최종적으로는 Object 생성자 함수 즉 constructor에 상속받는다. Object.prototype.constructor로 접근할 경우 object 인스턴스의 프로토타입을 만든 Object함수를 반환한다.
var o = {};
o.constructor === Object; // true
var o = new Object();
o.constructor === Object; // true
var a = [];
a.constructor === Array; // true
var a = new Array();
a.constructor === Array; // true
var n = new Number(3);
n.constructor === Number; // true
class Data {
constructor(value) {
}
}
const data = new Data()
data.constructor === Data; // true
객체의 속성이 열거 가능(enumerable)하면 흔히 아는 for… in, Object.keys(), Object.values(), Object.entries() spread 연산자와 같은 구문을 사용할 수 있다.
주의할 점은 enumerable과 이터러블을 혼동하면 안된다.
특정 객체의 속성에서 enumerable을 제어하는 방법
// defineProperty를 이용하는 방법
const obj = {a : 1, b : 2}
Object.defineProperty(obj, "a", {
enumerable : false
})
const defineObj = { ...obj } // 'a'속성에 대해 unenumerable
/** Object.create
* obj의 속성들을 상속받지만, 직접적으로는 해당 속성들을 소유하지 않는다.
* 즉 enumerable하지 않다기 보다는 프로토타입 체인으로 상속되었기 때문에 열거가 불가능. */
const createObj = Object.create(obj) // {}
/** setPrototypeOf
* 지정 된 객체를 특정객체의 프로토타입 속성을 상속해줌.
* 즉 enumerable하지 않다기 보다는 프로토타입 체인으로 상속되었기 때문에 열거가 불가능.
* 이 기능은 언어의 일부이므로, 여전히 엔진 개발자가 이 기능을 성능 좋게(이상적으로는) 구현해야 할 부담이 있습니다. 엔진 개발자가 이 문제를 해결할 때까지 성능이 걱정된다면 객체의 를 설정하는 것을 피해야 합니다 . 대신 원하는 를 사용하여 [[Prototype]]새 객체를 만듭니다
*/
const emptyObj = {}
Object.setPrototypeOf(emptyObj, obj) // {}
Object.defineProperty의 경우 정적 메서드로 객체에 새로운 속성을 직접 정의하거나 이미 존재하는 속성을 수정합니다.
const obj = {}
Object.defineProperty(obj, "a", {
value: 37,
writable: true,
enumerable: true,
configurable: true,
});
이때 우리는 6개의 속성을 정의 혹은 수정할 수 있습니다.
-
value
: obj.key에 접근하면 얻는 값. 초기 값은 당연히 undefined -
writable
: 값을 변경 가능한지에 대한 여부. 초기 값 false -
enumerable
: 열거 가능한지에 대한 여부. 초기 값 false -
configurable
: 삭제 가능 여부와 함께 descriptor의 속성을 변경가능한지 여부. 기본값 false -
getter
: obj.key에 접근 할때 동작 -
setter
: obj.key를 설정할 때 동작
const object = {}
Object.defineProperty(object, 'name', {
value : "hyun"
})
console.log(Object.getOwnPropertyDescriptor(object, 'name'))
// { value: 'hyun', writable: false, enumerable: false, configurable: false } // ⓐ
object.birth = 1997
console.log(Object.getOwnPropertyDescriptor(object, 'birth'))
// { value: 1997, writable: true, enumerable: true, configurable: true }
Object.defineProperty로 직접 속성 값을 정의하면 descriptor속성들은 초기 값이 유지된다.
const obj = {
name: '',
};
obj.name = 'hyun';
console.log(obj.name); // hyun
Object.defineProperty(obj, 'name', {
writable: false,
});
obj.name = 'mincho';
console.log(obj.name); // hyun
Object.defineProperty(obj, 'name', {
value: 'mincho'
})
console.log(obj.name); // mincho
writable
이 false면 object.key로 값을 변경할 수 없다. 하지만 Object.defineProperty로는 값을 변경할 수 있다.
const obj = {
name: 'mincho',
};
Object.defineProperty(obj, 'name', {
configurable: false,
});
delete obj.name; // 삭제가 되지 않음..
console.log(obj.name); // mincho
Object.defineProperty(obj, 'name', {
value: 'hyun',
});
console.log(obj.name); // hyun
Object.defineProperty(obj, 'name', {
writable: false,
});
Object.defineProperty(obj, 'name', {
writable: true,
}); // 에러 발생
Object.defineProperty(obj, 'name', {
enumerable: false,
}); // 에러 발생
Object.defineProperty(obj, 'name', {
configurable: true,
}); // 에러 발생
Object.defineProperty(obj, 'name', {
get() { ... },
}); // 에러 발생
Object.defineProperty(obj, 'name', {
set() { ... },
}); // 에러 발생
configurable
속성이 False일 경우 delete로 해당 속성을 제거할 수 없습니다. enumerable, configurable, getter, setter도 변경할 수 없습니다.
writable
은 true일 경우 변경은 가능 하지만 false로 변경하고 다시 true로 변경할 수 없습니다.