简介
ECMAScript 定义的对象中有两种特殊的属性, 这两种特殊的属性在你定义对象属性时就会赋予, 我们在必要时可以改写这两种特殊的属性让其属性的访问更加的合理化, 这两种特殊的属性称呼及作用如下:
数据属性: 通过对数据属性的设置, 我们可以让用户操作普通的数据(obj.name)时限制他们可以操作的权限, 可以让其数据变得不可修改、不可在for...in中被其枚举、不可以删除该数据并且不能让其改变原有的部分数据属性([[ Enumerable ]]、[[ Configurable ]])等。
访问器属性:
总的来说就是对对象中的属性进行一个设置、 比如当你不想让这个属性对外公开时你就可以用到以上的两种特殊属性。
数据属性
首先我们来看一下数据属性的具体特性:
描述特性 |
数据类型 |
描述 |
默认值 |
[[Value]] |
任何的ECMAScript类型 |
包含这个属性的数据值 |
undefined |
[[Writable]] |
Boolean |
如果该值为false,则该属性的[[Value]]特性,不能被改变 |
false |
[[Enumerable]] | Boolean | 如果该值为true, 则该属性可以用for...in 循环来枚举 |
false |
[[Configurable]] | Boolean | 如果该值为false,则该属性不能被删除,并且无法再次配置属性的特性, | false |
以下方法简介是我们在接下来的实践中会用到的:
Object.defineProperty:直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。
Object.getOwnPropertyDescriptor:返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
首先我们来查看一下数据属性是怎样的呢:
这里我们通过Object.getOwnPropertyDescriptor来获取我所定义的 fun 属性对应的数据属性, 可以看到返回的对象中的属性名字都是数据属性的具体特性名称, 那么我们来实践一下数据属性设定后的影响吧。
这里我们通过Object.defineProperty方法来进行设定:
这里可以明显看到当我们对obj中fun属性设置数据属性[[Value]]为"static"后, obj中fun原值是一个函数, 但现在已经改变为了"static"字符串。
由于在上面我们已经改写了obj.fun的数据属性[[Writable]], 所以在这里对fun属性进行改写是没有成功写入的。
当我们尝试对obj.fun属性进行删除、 在这里返回了false, 而后我们想再次修改fun属性的[[Enumerable]]的值时, 会报错,这是我们修改[[Configurable]]后的结果。
当我们尝试枚举obj的属性列表时, 这是我们修改[[Enumerable]]的结果。 如果想要枚举一个对象的所有属性名,可以用Object.getOwnPropertyNames方法来获取, 这里不再演示。
最后, 再次通过Object.getOwnPropertyDescriptor方法来查看fun的数据属性, 这时已经变为我们设置后的
访问器属性
描述特性 | 数据类型 | 描述 |
默认值 |
[[Get]] |
函数对象或者undefined |
该函数使用一个空的参数列表,能够在有权访问的情况下读取属性值。另见 get。 | undefined |
[[Set]] | 函数对象或者undefined |
该函数有一个参数,用来写入属性值, 另见set | undefined |
还有两个其它的属性, 和数据属性是一毛一样, 唯一不同就是此时[[Configurable]]代表了能不能转变成一个数据属性。
访问器属性的定义也是通过Object.defineProperty来进行的, 其使用方式也和数据属性的定义一样, 只是value和writable变为了get和set, 我不想进行无意义的实践, 下面我将说的是刚刚我没理解的访问其属性和数据属性。
最后
写这篇文章到一半的时候,我对数据属性和访问器属性的理解已经和原含义走了相反的路线, 一直以为这两个属性是作为对象属性(obj.fun)的附属品, 就像是附魔卡一样, 这就造成了我在对对象属性设置描述时使用同一种方法定义两种不同的描述时产生的困惑, 一个是我已经数据属性和访问器属性是可以共存的属性, 就像可以附魔多张魔法卡一样, 但当看到访问器属性和数据属性的描述时, 却有两个看似相同的描述, 让我好般不懂。
后来在这个问题的回答突然懂了, 原来访问器属性和数据属性是一种定义对象属性的内部形式的方法, 这两种属性定义是让对象属性类似从AD变为AP的方法,这会改变对象属性的表现形式,而不是附加特性, 严格而论就是:对象的属性有两种互不相干的表现形式。 我想很多读者在这里也懂了, 吾愚笨, 深觉此问题有趣也, 所以写在了最后。