속성 설명자는 ES5의 새로운 개념입니다. 해당 기능은 객체의 속성에 더 많은 제어를 추가하는 것입니다.
Object.defineProperty
속성 설명자를 연구하려면 먼저 Object.defineProperty 메서드에 대해 이야기해야 합니다. 이 메서드의 목적은 개체의 새 속성을 정의하거나 기존 속성을 수정하는 것입니다. 프로토타입은 다음과 같습니다.
Object.defineProperty(obj, prop, descriptor)
사용 예:
var obj = { };
Object.defineProperty(obj, 'attr', { value: 1 });
위의 코드 조각은 값이 1인 attr이라는 속성을 obj 객체에 추가합니다. 다음과 동일:
var obj = { };
obj.attr = 1;
이에 비해 Object.defineProperty의 작성 방법은 좀 더 복잡한 것 같습니다. 그러나 가장 큰 비밀은 세 번째 매개변수에 있습니다.
데이터 설명자
attr을 읽기 전용 속성으로 만들고 싶다면 쓰기 가능한 데이터 설명자를 추가할 수 있습니다.
var obj = { };
Object.defineProperty(obj, 'attr', {
값: 1,
쓰기 가능: 거짓
});
console.log(obj.attr);
obj.attr = 2; // 실패
console.log(obj.attr);
위 프로그램을 실행해 보면 두 번 출력된 attr의 값이 1이라는 것을 알 수 있는데, 이는 속성 쓰기에 실패했음을 의미한다. 그러나 할당문이 예외 없이 실행되지 않았기 때문에 이러한 결과는 다소 혼란스러울 수 있습니다. 큰 코드 조각에서 이러한 문제가 발생하면 문제 해결이 어려울 것이라고 상상해 보십시오. 실제로 엄격 모드에서 코드를 실행하면 예외가 발생합니다.
'use strict'; // 엄격 모드로 전환
var obj = { };
Object.defineProperty(obj, 'attr', {
값: 1,
쓰기 가능: 거짓
});
obj.attr = 2; // 예외 발생
속성이 열거될 수 있는지 여부를 제어할 수 있는 열거 가능한 또 다른 데이터 설명자를 살펴보겠습니다. 단순히 속성을 정의하는 경우 이 속성은 for...in 루프에서 열거될 수 있습니다.
var obj = { };
obj.attr = 1;
for (var i in obj) { console.log(obj[i]) }
열거형은 이를 "숨길" 수 있습니다:
var obj = { };
Object.defineProperty(obj, 'attr', {
값: 1,
열거 가능: false
});
for (var i in obj) { console.log(obj[i]) }
위의 코드를 실행하면 현재 attr 속성을 열거할 수 없기 때문에 콘솔에 아무 것도 출력되지 않는 것을 알 수 있습니다.
이 시점에서 궁금한 점이 있을 수 있습니다. 속성 설명자를 수정할 수 있나요? 예를 들어 읽기 전용 속성을 다시 쓰기 가능으로 정의할 수 있나요? 실제로 이는 속성 설명자를 변경할 수 있는지 여부를 제어하는 구성 가능한 다른 데이터 설명자에 따라 달라집니다.
var obj = { };
Object.defineProperty(obj, 'attr', {
값: 1,
쓰기 가능: false,
구성 가능: true
});
Object.defineProperty(obj, 'attr', {
쓰기 가능: true
});
obj.attr = 2;
위의 코드는 먼저 attr을 읽기 전용 속성으로 정의한 다음 이를 쓰기 가능으로 재정의합니다. 따라서 attr에 대한 쓰기는 성공적입니다.
액세스 설명자
액세스 설명자는 객체 지향의 get/set 접근자와 유사합니다.
var obj = { };
Object.defineProperty(obj, 'attr', {
설정: function(val) { this._attr = Math.max(0, val) },
가져오기: function() { return this._attr }
});
obj.attr = -1;
console.log(obj.attr) // 0
위의 코드에서 attr에 대한 액세스는 실제로 _attr에 대한 액세스가 되며, set 함수에서 최소값은 0으로 제한됩니다.
속성 설명자 가져오기
위 내용은 속성 설명자 설정에 관한 내용인데, 설정 설명자를 어떻게 구하나요? Object.getOwnPropertyDescriptor가 작업을 수행합니다.
var obj = { };
Object.defineProperty(obj, 'attr', {
값: 1,
쓰기 가능: false,
구성 가능: true
});
var desc = Object.getOwnPropertyDescriptor(obj, 'attr');
console.dir(desc);
객체 제어
앞서 언급한 Object.defineProperty는 객체의 속성에 대해 작동하는 반면, 아래에 언급된 세 가지 메서드는 객체에 직접 작동합니다.
Object.preventExtensions는 객체가 새로운 속성을 갖는 것을 방지할 수 있습니다.
var obj = { };
obj.attr = 1;
Object.preventExtensions(obj);
obj.attr2 = 2; //실패
Object.seal은 객체에 수정 가능한 속성 값만 갖도록 만들 수 있습니다(속성이 읽기 전용인 경우 속성 값도 수정할 수 없습니다):
var obj = { };
obj.attr = 1;
Object.seal(obj);
obj.attr = 1.5;
obj.attr 삭제 // 실패
Object.freeze는 객체를 완전히 수정할 수 없도록 만들 수 있습니다.
var obj = { };
obj.attr = 1;
Object.freeze(obj);
obj.attr = 1.5; // 실패
obj.attr2 = 2; //실패
그렇다면 객체가 방지 확장, 봉인 또는 동결되었는지 어떻게 알 수 있습니까? 대답은 Object.isExtensible, Object.isSealed 및 Object.isFrozen을 각각 호출하는 것입니다. 이 세 가지 함수의 사용법은 상대적으로 간단하고 더 이상 번거롭지 않습니다.
일반적으로 객체는 속성 설명자를 통해 더욱 엄격하게 제어할 수 있으며, 프로그램 로직의 엄격함을 강화할 수 있습니다. 유일한 단점은 ES5가 기본적으로 IE9에서만 구현된다는 것입니다(IE9는 아직 국내에서는 strict 모드를 지원하지 않습니다). IE8 점유율은 여전히 상대적으로 높지만, 이 세트는 현재 모바일 브라우저와 Node.js에서만 사용할 수 있습니다.