2장 값을 잘다루기 - chhw130/Front-Basic-Deep-Dive GitHub Wiki

내가 궁금했던 사항들

프로토타입 메서드 Object.prototype.constructor

모든 객체는 특정 속성을 찾기위해 프로토타입 체이닝이 이뤄지고 최종적으로는 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

MDN관련 문서


enumerable

객체의 속성이 열거 가능(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) // {}

객체의 속성에 대해서 (feat Object.defineProperty)

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를 설정할 때 동작

obj.key로 값을 설정할 때와 Object.defineProperty로 값을 설정할 때의 차이

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속성들은 초기 값이 유지된다.

writable

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로는 값을 변경할 수 있다.

configurable

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로 변경할 수 없습니다.

Object.defineProperty 정리

⚠️ **GitHub.com Fallback** ⚠️