Share
Sign In

객체의 속성 설정

개요

자바스크립트의 객체 property들은 각각의 설정값들을 지닌다.
일반 설정과 데이터 접근 설정으로 나뉘는데, 이 속성 정의에 따라 property의 쓰임이 달라진다.
공통
configurable: 설정 재조정과 프로퍼티 삭제 여부 / 기본값 false
enumerable: 열거 여부 (in Object.keys(), or for-in statement) / 기본값 false
일반 설정자
value: 프로퍼티의 값 / 기본값 undefined
writable: true 일 경우 값을 할당할 수 있다. / 기본값 false
접근 설정자 (Getter, Setter)
get: 속성값을 얻는 함수이다. 즉 해당 속성의 값을 리턴한다. / 기본값 undefined
set: 속성값을 설정하는 함수이다. 인자는 value하나만 올 수 있다. / 기본값 undefined

Object.defineProperty(), 공통, 일반 설정자

Object 생성자의 static 메소드인 definedProperty는 이러한 객체의 설정들을 세부적으로 조정할 수 있도록 돕는다. 용법은 다음과 같다.
Object.defineProperty(obj, prop, descriptor)
첫번째 인자인 obj는 메소드의 대상이 되는 객체이다. 두번째 인자 prop은 설정할 프로퍼티의 이름이며, 마지막 인자 descriptor에서 이 설정들을 객체의 형태로 조정한다. 이를테면, 다음과 같다.
const obj = {}; Object.defineProperty(obj, 'foo', { __proto__: null, value: 'bar' writable: true }); console.log(obj)
value, writable외의 기타 설정이 없으므로 모두 default설정으로 들어간다. 즉 configurable, enumerable 속성이 모두 false인 것이다. 다음 코드를 실행해보자.
obj.foo = 1; console.log(obj) // 안 바뀜, writable 불가 Object.defineProperty(obj, 'foo', { __proto__: null, value: 'foobar', }); // CANNOT REDEFINE PROPERTY 에러, configurable이 false이기 때문 Object.defineProperty(obj, 'foo', { writable: false; }); // 단, writable 값만은 configurable == false 라도, 오직 false 로는 바뀔 수 있다 for(let i in obj) { console.log(i) } Object.keys(obj) // 둘 다 빈값으로 나옴, enumerable이 false이기 때문
그렇다면 객체 리터럴로 생성한 프로퍼티의 경우는 어떨까?
const obj2 = { foo: 'this is writable, enumerable, and configurable!!' } obj2.foo = 'is this writable, enumerable, and configurable ?' console.log(obj2.foo) // writable!! for (let i in obj2) { console.log(i) } console.log(Object.keys(obj2)) // enumerable! Object.defineProperty(obj2, 'foo', { value: '...' }) // configurable !!
재선언, 열거, 재설정이 모두 가능하다. 즉 객체 리터럴로 생성한 프로퍼티는 다음과 같다.
const obj2 = { foo: 'bar' } // 는 다음과 같다. Object.defineProperty(obj2, 'foo', { value: 'bar', writable: true, enumerable: true, configurable: true })

접근 설정자

접근 설정자는 getter, setter를 의미한다. 일반적으로 사용하는 getter, setter함수는 이 속성의 축약형이다.
접근 설정자는 writable속성이나, value 속성과 같은, value를 다루는 속성과는 함께 쓰일수 없다. 즉 다음과 같은 코드는 에러가 난다.
const obj3 = {} let temp = 0; Object.defineProperty(obj3, 'foo', { value: 0, writable: true, get (){ return temp; } }); // TypeError: Invalid property descriptor. // Cannot both specify accessors and a value or writable attribute
Getter나 Setter는 다음 형태로도 사용이 가능하다 (es6 Proxy로도 비슷한 동작을 만들 수 있다)
function Archiver() { let temp = null; const archive = []; Object.defineProperty(this, 'temp', { get() { console.log('get!'); return temp; }, set(value) { temp = value; archive.push({ val: temp }); } }); this.getArchive = () => archive; } const arc = new Archiver(); arc.temp = 'temp1'; arc.temp = 'temp2'; arc.getArchive();
위의 예에서 볼 수 있듯 Getter나 Setter를 사용하면 사용자가 객체를 추가하거나, 변경할 때 임의의 설정이 가능하다. 이러한 특성을 이용해 Vue와 같은 프레임워크에서는 Reactivity, 즉 반응성을 정의한다.

참고