概念
创新互联拥有网站维护技术和项目管理团队,建立的售前、实施和售后服务体系,为客户提供定制化的成都网站制作、成都网站建设、网站维护、香港机房服务器托管解决方案。为客户网站安全和日常运维提供整体管家式外包优质服务。我们的网站维护服务覆盖集团企业、上市公司、外企网站、商城网站定制开发、政府网站等各类型客户群体,为全球成百上千家企业提供全方位网站维护、服务器维护解决方案。
ECMAScript 5 中定义了一个名叫“属性描述符”的对象,用于描述了的各种特征。属性描述符对象有4个属性:
除了上面的属性,还有两个存取器属性,分别是get和set,可以代替value和writable。
使用
“属性描述符”对象只能在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属性已经被设置为不可配置,所以这里修改writable会抛出类型错误异常。
通过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修改为false。
- 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'
只指定set不能读,如果尝试读取该属性值,返回undefined。(红宝书上说在严格模式下才抛出异常,但没有)
- 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来判断对象是否封闭(sealed)。
- 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方法,而且不会抛出异常,但如果set方法是改变该对象的属性,则不能修改成功)
使用Object.isFrozen来检测对象是否冻结(frozen)。
- 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'
结语
我对属性描述符很不熟悉,主要是因为平时用得少。不过最近,开始学写一些小的库(虽然很挫),就感觉属性描述符有使用的场景了。我暂时能想到的就是将库对象的一些属性设置为只读,以防止对象的一些属性被用户重写覆盖了。还有一个用法是在知乎和学vue的时候知道的,就是通过getter和setter实现“监听”对象属性的数据更新(在这里挖一个坑。后面学习一下这种方法,再写一篇“监听”对象属性的数据更新的文章)。
***,如果大家知道更多属性描述符的使用后场景,希望大家能在评论区留下你们的高见。
分享文章:JS属性特性(属性描述符)
标题路径:http://www.gawzjz.com/qtweb/news15/181465.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联