JS 속성 특성(속성 설명자)
ECMAScript 5는 다양한 특성을 설명하는 데 사용되는 "속성 설명자"라는 개체를 정의합니다. "속성 설명자" 개체는 Object.defineProperty 또는 Object.defineProperties에서만 사용할 수 있습니다.
Concept
ECMAScript 5는 다양한 특성을 설명하는 데 사용되는 "속성 설명자"라는 객체를 정의합니다. 속성 설명자 객체에는 4가지 속성이 있습니다.
configurable: 설명하는 속성의 수정을 제어하는 구성 가능성으로, 속성의 특성이 수정될 수 있는지 여부, 속성이 접근자 속성으로 수정될 수 있는지 여부, 또는 속성을 재정의하기 위해 삭제를 통해 속성을 삭제할지 여부입니다. 기본값은 true입니다.
열거 가능: 열거 가능성, for-in 순회를 통해 속성을 얻을 수 있는지 여부를 나타냅니다. 기본값은 true입니다.
writable: 쓰기 가능성, 속성 값을 수정할 수 있는지 여부를 나타냅니다. 기본값은 true입니다.
값: 데이터 속성, 속성 값을 나타냅니다. 기본값은 정의되지 않습니다.
위 속성 외에도 값과 쓰기 가능을 대체할 수 있는 get 및 set이라는 두 가지 접근자 속성이 있습니다.
get: 속성을 읽을 때 호출되는 함수입니다. get만 지정하면 속성이 읽기 전용임을 의미합니다. 기본값은 정의되지 않습니다.
set: 속성을 쓸 때 호출되는 함수입니다. set만 지정한다는 것은 속성이 쓰기 전용 속성임을 의미합니다. 기본값은 정의되지 않습니다.
"속성 설명자" 개체 사용은 Object.defineProperty 또는 Object.defineProperties에서만 사용할 수 있습니다.
API 사용법
Object.defineProperty: https://developer.mozilla.org...
Object.defineProperties: https://developer.mozilla.org. ..
var hello = {} Object.defineProperty(hello, 'girl', { configurable: false, enumberable: false, writable: true, value: 'sexy' }) // 存取器 Object.defineProperty(hello, 'woman', { configurable: false, enumberable: false, get: function() { return this.girl }, set: function(val) { this.girl = val } }) // 定义多个属性 Object.defineProperties(hello, { boy: { configurable: false, enumberable: false, writable: false, value: 'handsome' }, man: { configurable: false, enumberable: false, writable: true, get: function() { return this.boy } } })
Object.defineProperty 또는 Object.defineProperties를 사용하여 생성 또는 수정이 허용되지 않는 속성을 조작(생성 또는 수정)하는 경우 유형 오류 예외가 발생합니다.
// 此例子运行在前面的例子的基础上 Object.defineProperty(hello, 'boy', { writable: true }) // Uncaught TypeError: Cannot redefine property: boy
boy 속성은 이전에 구성 불가능으로 설정되었기 때문에 여기에서 쓰기 가능 항목을 수정하면 유형 오류 예외가 발생합니다.
속성 설명자는 Object.getOwnPropertyDescriptor 또는 Object.getOwnPropertyDescriptors를 통해 얻을 수 있습니다.
API 사용법
Object.getOwnPropertyDscriptor: https://developer.mozilla.org...
Object.getOwnPropertyDescriptors: https://developer.mozilla.org. ..
규칙
var rules = { common: 'test' }
속성을 구성할 수 없는 경우 구성 가능성과 열거 가능성을 수정할 수 없습니다.
Object.defineProperty(rules, 'rule1', { configurable: false, enumberable: false }) // 修改configurable会抛出类型错误异常 Object.defineProperty(rules, 'rule1', { configurable: true }) // Uncaught TypeError: Cannot redefine property: rule1 // 修改enumberable不会抛出异常,但enmuberable没有被修改 Object.defineProperty(rules, 'rule1', { enumberable: true }) Object.getOwnPropertyDescriptor(rules, 'rule1') // Object {value: undefined, writable: false, enumerable: false, configurable: false}
접근자 속성을 구성할 수 없는 경우 get 및 set 메서드를 수정할 수 없으며 데이터 속성으로 변환할 수도 없습니다.
Object.defineProperty(rules, 'rule2', { configurable: false, enumberable: false, get: function() { return this.common }, set: function(val) { this.common = val } }) // 修改get或者set方法会抛出类型错误异常 Object.defineProperty(rules, 'rule2', { get: function() { return this.common + 'rule2' } }) // Uncaught TypeError: Cannot redefine property: rule2 Object.defineProperty(rules, 'rule2', { set: function(val) { this.common = 'rule2' } }) // Uncaught TypeError: Cannot redefine property: rule2 // 将它转换为数据属性同样会抛出类型错误异常 Object.defineProperty(rules, 'rule2', { value: 'rule2' }) // Uncaught TypeError: Cannot redefine property: rule2
데이터 속성을 구성할 수 없으면 동시에 접근자 속성으로 변환할 수 없으며 쓰기 가능성을 false에서 true로 수정할 수는 없지만 true에서 true로 수정할 수는 있습니다. 거짓.
Object.defineProperty(rules, 'rule3', { configurable: false, writable: false, value: 'rule3' }) // 修改writable为true会抛出类型错误异常 Object.defineProperty(rules, 'rule3', { writable: true }) Object.defineProperty(rules, 'rule4', { configurable: false, writable: true, value: 'rule4' }) // 可以修改writable为false Object.defineProperty(rules, 'rule4', { writable: false }) Object.getOwnPropertyDescriptor(rules, 'rule4') // Object {value: "rule4", writable: false, enumerable: false, configurable: false}
데이터 속성이 구성 불가능하고 쓰기 불가능하면 해당 값을 수정할 수 없습니다. 구성 가능하지만 쓰기 가능하지 않으면 해당 값을 수정할 수 있습니다(실제로 쓰기 가능으로 표시됨). 그런 다음 해당 값을 수정하고 마지막으로 다시 쓸 수 없는 것으로 표시합니다.
사실 여기서 언급한 수정값은 Object.defineProperty나 Object.defineProperties 메소드를 통해 수정된 것입니다. 데이터 속성을 구성할 수 없는 경우 직접 할당을 통해 속성 값을 수정할 수 없습니다.
Object.defineProperty(rules, 'rule5', { configurable: false, writable: false, value: 'rule5' }) // 修改属性值会抛出类型错误异常 Object.defineProperty(rules, 'rule5', { value: 'rule55' }) // Uncaught TypeError: Cannot redefine property: rule5 rules.rule5 = 'rule55' // 值没有被修改,也不会抛出异常 rules.rule5 // 'rule5' Object.defineProperty(rules, 'rule6', { configurable: true, writable: false, value: 'rule6' }) // 修改属性值 Object.defineProperty(rules, 'rule6', { value: 'rule66' }) rules.rule6 // 'rule66' rules.rule6 = 'rule6' // 值没有被修改,也不会修改 rules.rule6 // 'rule6'
지정된 세트만 읽을 수 없습니다. 속성 값을 읽으려고 하면 정의되지 않은 값이 반환됩니다. (Red Book에서는 예외가 엄격 모드에서만 발생한다고 나와 있지만 그렇지 않습니다.)
Object.defineProperty(rules, 'rule7', { get: function() { return this.common } }) rules.rule7 = 'rule7' // Uncaught TypeError: Cannot redefine property: rule7
객체가 확장 가능하지 않은 경우 기존 자체 속성을 편집할 수는 있지만 새 속성을 추가할 수는 없습니다. 그것.재산.
객체 확장성을 작동하기 위한 API에는 Object.preventExtensions, Object.seal 및 Object.freeze의 세 가지가 있습니다.
API 사용법
Object.preventExtensions: https://developer.mozilla.org...
Object.seal: https://developer.mozilla.org. ..
Object.freeze: https://developer.mozilla.org...
Object.isExtensions: https://developer.mozilla.org...
Object.isSealed: https://developer.mozilla.org...
Object.isFrozen: https://developer.mozilla.org...
Object.preventExtensions 사용 객체는 확장 불가능한 객체로 변환될 수 있습니다.
객체가 확장 가능한지 확인하려면 Object.isExtensions를 사용하세요.
var ex = {} Object.defineProperty(ex, 'ex1', { configurable: true, writable: true, value: 'ex1' }) Object.isExtensible(ex) // true Object.preventExtensions(ex) Object.isExtensible(ex) // false // 可以修改已有的属性 Object.defineProperty(ex, 'ex1', { writable: false, value: 'ex11' }) Object.getOwnPropertyDescriptor(ex, 'ex1') // Object {value: "ex11", writable: false, enumerable: false, configurable: true} // 添加属性会抛出类型错误异常 Object.defineProperty(ex, 'ex2', { value: 'ex2' }) // Uncaught TypeError: Cannot define property:ex2, object is not extensible.
객체를 확장 불가능으로 변환하는 것 외에도 Object.seal을 사용하면 객체 자체의 모든 속성을 구성 불가능으로 변환할 수도 있습니다. 즉, 새 속성을 개체에 추가할 수 없으며 기존 속성을 삭제하거나 구성할 수 없습니다. 여기서는 이전과 동일한 규칙을 따릅니다.
객체가 봉인되었는지 확인하려면 Object.isSealed를 사용하세요.
var se = {} Object.defineProperty(se, 'se1', { configurable: true, writable: false, value: 'se1' }) Object.isSealed(se) // false Object.seal(se) Object.isSealed(se) // true // 修改已有的属性会抛出类型错误异常 Object.defineProperty(se, 'se1', { writable: true, value: 'se11' }) // Uncaught TypeError: Cannot redefine property: se1 // 添加属性会抛出类型错误异常 Object.defineProperty(se, 'se2', { value: 'se2' }) // Uncaught TypeError: Cannot define property:se2, object is not extensible.
Object.freeze를 사용하면 객체를 확장 불가능으로 변환하고 해당 속성을 구성 불가능으로 변환하는 것 외에도 자신의 속성을 읽기 전용으로 변환할 수도 있습니다. (객체를 설정한 경우 접근자 속성은 영향을 받지 않으며 set 메서드를 계속 호출할 수 있으며 예외가 발생하지 않습니다. 그러나 set 메서드가 객체의 속성을 변경하면 성공적으로 수정할 수 없습니다.)
객체가 동결되었는지 여부를 감지하려면 Object.isFrozen을 사용하세요.
var fr = {} Object.defineProperty(fr, 'fr1', { configurable: true, writable: false, value: 'fr1' }) Object.isFrozen(fr) // false Object.freeze(fr) Object.isFrozen(fr) // true // 修改已有的属性会抛出类型错误异常 Object.defineProperty(fr, 'fr1', { writable: true, value: 'fr11' }) // Uncaught TypeError: Cannot redefine property: fr1 // 添加属性会抛出类型错误异常 Object.defineProperty(fr, 'fr2', { value: 'fr2' }) // Uncaught TypeError: Cannot define property:fr2, object is not extensible. fr.fr1 = 'fr11' // 不能修fr1属性 fr.fr1 // 'fr1' var set = {} Object.defineProperty(set, 'set1', { configurable: true, value: 'set1' }) Object.defineProperty(set, 'set2', { configurable: true, set: function(val) { this.set1 = val } }) Object.isFrozen(set) // false Object.freeze(set) Object.isFrozen(set) // true set.set2 = 'set2' set.set1 // 'set1'
결론
저는 속성 설명자를 거의 사용하지 않기 때문에 매우 익숙하지 않습니다. 그러나 최근에 나는 몇몇 작은 라이브러리를 작성하는 법을 배우기 시작했고(비록 매우 실망스러웠지만) 속성 설명자를 사용하는 시나리오가 있다는 것을 느꼈습니다. 일단 제가 생각할 수 있는 것은 사용자가 객체의 일부 속성을 덮어쓰는 것을 방지하기 위해 라이브러리 객체의 일부 속성을 읽기 전용으로 설정하는 것입니다. Zhihu에서 Vue를 배울 때 배운 또 다른 사용법이 있는데, 이는 getter 및 setter를 사용하여 객체 속성의 데이터 업데이트를 "모니터링"하는 것입니다