JavaScript/객체

[JavaScript]객체 속성(writable, enumerable, configurable)

DevStory 2021. 12. 7.

속성의 본질적인 속성 설명자

JavaScript의 객체는 다음과 같이 <key> : <value> 쌍으로 이루어진 존재입니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

name이라는 key는 'Kang JaeSeong' value와 매핑되며, age라는 key는 30이라는 value와 매핑됩니다.

 

Object.getOwnPropertyDescriptor() 함수를 사용하면, 객체의 속성에 대한 모든 설명을 확인할 수 있습니다. 다음은 userInfo 객체의 name 속성에 대한 설명자입니다.

console.log(Object.getOwnPropertyDescriptor(userInfo, 'name'));

실행 결과

속성 설명자에 value, writable, enumerable 및 configurable 네 가지 설명자가 존재하며, value를 제외한 속성의 값은 기본적으로 true입니다.

 

만약, userInfo 객체에 존재하지 않는 속성에 대한 설명자를 확인하는 경우 Object.getOwnPropertyDescriptor() 함수는 undefined를 반환합니다.

console.log(Object.getOwnPropertyDescriptor(userInfo, 'highSchool'));

실행 결과


writable

writable 속성은 해당 속성의 값을 변경할 수 있는지 여부를 나타냅니다. Object.defineProperty() 함수는 설명자에 존재하는 속성의 값을 설정할 수 있습니다.

 

다음은 Object.defineProperty() 함수로 설명자의 writable 속성 값을 false로 변경합니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

Object.defineProperty(userInfo, 'name', {writable: false});

console.log(Object.getOwnPropertyDescriptor(userInfo, 'name'));

실행 결과

 

userInfo객체의 name 속성의 설명자 writable 속성 값을 false로 변경 후 name 속성의 값을 변경하면 적용되지 않습니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

Object.defineProperty(userInfo, 'name', {writable: false});

userInfo.name = 'Kim JaeSeong';

console.log(userInfo);

실행 결과

 

그러나 다음과 같이 중첩된 객체인 경우(속성이 객체인 경우)에는 writable의 속성을 false로 설정해도 값이 변경되는 문제가 존재합니다.

const userInfo = {
  name: {
    firstName: 'Kang',
    lastName: 'JaeSeong'
  },
  age: 30,
  address: 'Busan'
}

Object.defineProperty(userInfo, 'name', {writable: false});

userInfo.name.firstName = 'Kim';

console.log(userInfo);

실행 결과

 

객체는 값을 가지는 형식(Call by value)이 아니라 값을 참조하는 형식(Call by reference)이므로 중첩된 객체의 속성을 변경하는 것을 막지 않습니다.

 

만약, userInfo.name 객체 속성의 값 변경, 속성 추가, 속성 제거를 방지하고 싶은 경우 Object.freeze() 함수를 사용합니다.

Object.freeze(userInfo.name);

 

다음은 Object.freeze() 함수 호출 후 userInfo.name.firstName의 값을 변경하는 예제입니다.

const userInfo = {
  name: {
    firstName: 'Kang',
    lastName: 'JaeSeong'
  },
  age: 30,
  address: 'Busan'
}

Object.freeze(userInfo.name);

userInfo.name.firstName = 'Kim';

console.log(userInfo);

실행 결과


enumerable

기본적으로 객체의 속성은 열거(enumerable) 가능하므로 for...in 반복문으로 접근할 수 있습니다. 그러나 enumerable 속성을 false로 설정하면 객체의 속성을 열거할 수 없습니다.

 

다음은 enumerable 속성이 true일 때, for...in 반복문으로 객체의 속성을 접근하는 예제입니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

console.log(Object.getOwnPropertyDescriptor(userInfo, 'name').enumerable);

for (const key in userInfo) {
  console.log(`key : ${key}`);
}

실행 결과

다음은 userInfo.name 속성의 enumerable을 false로 변경 후 for...in 반복문으로 객체의 속성을 접근하는 예제입니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

Object.defineProperty(userInfo, 'name', {enumerable: false});

console.log(Object.getOwnPropertyDescriptor(userInfo, 'name').enumerable);

for (const key in userInfo) {
  console.log(`key : ${key}`);
}

configurable

configurable 속성은 false로 설정되면 해당 속성을 잠그고 enumerable 및 configurable을 다시 변경하는 것을 방지합니다. 그리고 해당 속성을 삭제하지 못하도록 방지합니다. 하지만 쓰기(writable)는 가능합니다.

 

다음은 configurable 속성을 false로 변경 후 enumerable 속성을 false로 변경하는 예제입니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

Object.defineProperty(userInfo, 'name', {configurable: false});

console.log(Object.getOwnPropertyDescriptor(userInfo, 'name'));

Object.defineProperty(userInfo, 'name', {enumerable: false});

실행 결과

마찬가지로 configurable 속성을 다시 true로 변경하는 경우 TypeError가 발생합니다.

 

다음은 configurable 속성이 false인 경우 delete 키워드로 속성을 제거하는 예제입니다.

const userInfo = {
  name: 'Kang JaeSeong',
  age: 30,
  address: 'Busan'
}

Object.defineProperty(userInfo, 'name', {configurable: false});

delete userInfo.name;

console.log(userInfo);

실행 결과

위에서 언급했듯이 configurable이 false인 속성은 제거되지 않습니다.

반응형

댓글