JavaScript

[JavaScript] 객체 프로퍼티 설정

FRDYtheme 2022. 12. 6. 22:18

객체에 담긴 자료를 프로퍼티라고 하고 프로퍼티는 '키: 값'의 구조를 가짐.

하지만 객체 프로퍼티는 값(value)과 함께 플래그(flag)라 불리는 속성 세 가지를 가짐.

-

평범한 방식으로 프로퍼티를 만들면 해당 프로퍼티의 플래그는 모두 true이며 언제든 수정이 가능하다.


플래그를 얻는 메서드

Object.getOwnPropertyDescriptor(obj, propertyName);
// obj : 정보를 얻고자 하는 객체
// propertyName : 정보를 얻고자 하는 객체 내 프로퍼티

메서드를 호출하면 프로퍼티 설명자"desriptor"라고 불리는 객체가 반환되고 여기에 프로퍼티 값과 플래그 정보가 있음.

-

let user = {
  name: "friday"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

console.log(descriptor);

객체 user의 프로퍼티 'name'의 값과 플래그 정보.

  • writable : true면 값을 수정할 수 있다  /  false면 읽기만 가능
  • enumerable : true면 반복문을 사용해 나열 가능  /  false 면 나열 불가능.
  • configurable : true면 프로퍼티 삭제나 플래그 수정 가능  /  false면 불가능

플래그를 변경하는 메서드

Object.defineProperty(obj, propertyName, descriptor)
// obj, propertyName : 설명자를 적용하고 싶은 객체와 객체 프로퍼티
// descriptor : 적용하고자 하는 프로퍼티 설명자

객체에 해당 프로퍼티가 있으면 플래그를 변경해주며,

프로퍼티가 없으면 인수로 넘겨받은 정보를 이용해 새로운 프로퍼티를 생성.

 

이때 플래그 정보가 없으면 값이 자동으로 false가 된다.

let user = {}; // 빈 객체 생성

Object.defineProperty(user, "name", {value: "friday"});
// 객체 user에 프로퍼티 name을 추가하고 friday 값 할당

console.log(user); // friday

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

console.log(descriptor);
// defineProperty로 프로퍼티를 생성했지만 플래그를 명시하지 않았기 때문에
// 모든 플래그가 false.

Object.defineProperty(user, "age", {value: "32", writable: true, enumerable: true, configurable: true});
// 프로퍼티를 추가할 때 각 플래그의 값은 명시해줘야 함.

let descriptor2 = Object.getOwnPropertyDescriptor(user, 'age');

console.log(descriptor2);

플래그 값을 명시하지 않은 name은 플래그 값이 모두 false

-

플래그 값을 명시한 age는 모든 플래그 값이 true


writable 플래그

프로퍼티의 값 수정을 제어하는 플래그

let user = {}; // 빈 객체 생성

Object.defineProperty(user, "name", {value: "friday", enumerable: true, configurable: true});
// writable의 값을 명시하지 않았기 때문에 false.

console.log(user.name); // friday

user.name = 'monday'; // 엄격모드 : error, 비엄격모드 : error는 안 나지만 변경 불가능.
console.log(user.name); // friday

 

enumerable 플래그

for...in으로 객체 내 프로퍼티를 순회 호출 여부를 제어하는 플래그

let user = {
  name: 'friday',
  age: 32,
  height: 184,
  weight: 80,
};

for(let i in user) { // i: 키, user[i]: 값
  console.log(`${i}:${user[i]}`);
}

Object.defineProperty(user, "name", {enumerable: false});

for(let i in user) { // i: 키, user[i]: 값
  console.log(`${i}:${user[i]}`);
}
// enumerable의 값이 false가 된 name은 반복문으로 순회 불가능.

 

configurable 플래그

프로퍼티의 삭제나 플래그 수정 여부를 제어하는 값( configurable의 값이 false면 defineProperty로도 수정이 불가능하기 때문에 수정, 제거가 불가능한 프로퍼티 생성 가능 )-*대표적으로 내장 객체 Math의 프로퍼티 PI가 있음

파이는 값을 수정할 수도 삭제할 수도 없는 프로퍼티.

configurable이 false면 플래그의 삭제나 값 수정이 불가능.

(writable의 경우 true에서 false로 수정은 가능하지만 false에서 true로의 수정은 불가능.)

접근자 프로퍼티 get / set 을 변경할 수 없지만 새롭게 만드는 것은 가능.


Object.defineProperties

여러 프로퍼티를 한 번에 정의할 수 있는 메서드

 

-

Object.getOwnPropertyDescriptors

여러 프로퍼티의 설명자를 한 번에 호출하는 메서드.

  let user = {}; // 빈 객체 생성.

  Object.defineProperties(user, {
    name: { value: 'kgh', writable: true, enumerable: true, configurable: true },
    age: { value: 32, writable: true },
    height: { value: 180, enumerable: true },
  })

  console.log(Object.getOwnPropertyDescriptors(user));

Object.defineProperties

Object.getOwnPropertyDescriptors

플래그 포함 객체 복사

-

for ...in을 사용한 객체 복사는 플래그 정보를 복사하지 않고, 심볼형 프로퍼티도 놓치지만

위 두 메서드를 조합해서 객체를 복사하면 플래그, 심볼형 프로퍼티를 포함한 모든 설명자 전체를 반환.

 

바로 위 설명의 user 객체를 복사해보자

  let clone = Object.defineProperties({},
    Object.getOwnPropertyDescriptors(user)
  )
  
  console.log(clone);

아래는 복사된 객체 clone.


출처 : https://ko.javascript.info/property-descriptors