ECMAScript 5中属性的特性值

Posted Fogwind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ECMAScript 5中属性的特性值相关的知识,希望对你有一定的参考价值。

这是《javascript高级程序设计(第三版)》第六章相关内容的总结。

ECMAScript中有两种属性:数据属性和访问器属性。每种属性都有四个特性值。

数据属性的四个特性值:

[[Configurable]]:表示能否通过delete删除属性;能否修改属性的特性值;能否把属性修改为访问器属性。直接在对象上定义的属性,该特性的默认值为true。

[[Enumerable]]:表示能否通过for-in循环返回属性。直接在对象上定义的属性,该特性的默认值为true。

[[Writable]]:表示能否修改属性的值。直接在对象上定义的属性,该特性的默认值为true。

[[Value]]:包含这个属性的数据值。读取属性值的时候。从这个位置读;写入属性值的时候,把新值保存在这个位置。该特性的默认值为undefined。

访问器属性的四个特性:

访问器属性只能通过相应的方法设置,不能在对象上直接设置。

[[Configurable]]:表示能否通过delete删除属性;能否修改属性的特性值;能否把属性修改为数据属性。

[[Enumerable]]:表示能否通过for-in循环返回属性。

[[Get]]:在读取属性时调用的函数。该特性的默认值为undefined。

[[Set]]:在写入属性时调用的函数。该特性的默认值为undefined。

ECMAScript 5中操作属性特性的方法有3个:

Object.defineProperty():该方法用来设置单个属性的特性。它接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中描述符对象的属性必须是:configurable、enumerable、writable、value、get、set中的一个或多个。当然要根据属性类型选择。

Object.defineProperties():这个方法是上一个方法的增强版,可以同时设置多个属性的特性。它接收两个对象参数:第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对应(通过例子看,一目了然)。

Object.getOwnPropertyDescriptor():这个方法返回一个描述符对象,可以取得给定属性的特性的值。它接收两个参数:属性所在的对象和要读取其特性的属性名称。如果是数据属性,返回的对象有configurable、enumerable、writable、value四个属性;如果是访问器属性,返回的对象有configurable、enumerable、get、set四个属性。

例1

 1 <script type="text/javascript">
 2 var a = {
 3    name: \'A\',
 4    type: \'object\'
 5 }
 6 //修改直接在对象上定义的属性的值
 7 Object.defineProperty(a,\'type\',{
 8      value: \'car\'
 9 });
10 //用Object.defineProperty()方法给对象添加属性
11 Object.defineProperty(a,\'style\',{
12      value: \'no\'
13 });
14 //设置访问器属性
15 Object.defineProperty(a,\'country\',{
16      get: function() {
17         return \'none\';
18      }
19 });
20 
21 var b = Object.getOwnPropertyDescriptor(a,\'type\');
22 alert(b.configurable);//true
23 alert(b.enumerable);//true
24 alert(b.writable);//true
25 
26 var c = Object.getOwnPropertyDescriptor(a,\'style\');
27 alert(c.configurable);//false
28 alert(c.enumerable);//false
29 alert(c.writable);//false
30 
31 var d = Object.getOwnPropertyDescriptor(a,\'country\');
32 alert(a.country);//none
33 alert(d.configurable);//false
34 alert(d.enumerable);//false
35 alert(d.set);//undefined
36 alert(d.get);//输出get后面完整的匿名函数
37 </script>

通过上面的例子可以看到,用Object.defineProperty()方法给对象添加新属性,该属性的未指定的特性值要么默认为false,要么默认(set)为undefined,说明用Object.defineProperty()方法添加的新属性除非明确设置,否则一旦设置完成后是不可配置和更改的。而原本直接定义在对象上的属性,用Object.defineProperty()方法修改,未指定的特性值仍然默认为true,还是可以配置和更改的。

例2

 1 var a = {
 2    name: \'A\',
 3    type: \'object\'
 4 }
 5 //修改直接在对象上定义的属性的值
 6 Object.defineProperty(a,\'type\',{
 7      configurable: false,
 8      value: \'car\'
 9 });
10 
11 delete a.type;
12 var b = Object.getOwnPropertyDescriptor(a,\'type\');
13 
14 console.log(a.type);//car
15 console.log(b.configurable);//false
16 
17 Object.defineProperty(a,\'type\',{
18      configurable: true
19 });

上面代码在火狐的Firebug中会报错:

意思就是说,一旦把configurable设置为false,就改不回来了。书上说,此时再调用Object.defineProperty()方法修改除writable的特性,都会导致错误。但是,我觉得这要根据这个属性是怎么添加到对象上的来区分。

先看直接在对象上直接定义的属性:

 1 var a = {
 2    name: \'A\',
 3    type: \'object\'
 4 }
 5 //修改直接在对象上定义的属性的值
 6 Object.defineProperty(a,\'type\',{
 7      configurable: false,
 8      value: \'car\'
 9 });
10 
11 console.log(a.type);//car
12 console.log(b.configurable);//false
13 
14 Object.defineProperty(a,\'type\',{
15   writable: false,
16   value: \'to\'
17 });
18 
19 var b = Object.getOwnPropertyDescriptor(a,\'type\');
20 console.log(b.value);//to
21 console.log(b.writable);//false
22 console.log(a.type);//to

输出结果:

再调用Object.defineProperty()方法修改除writable的特性(这里修改了value的值),没有导致错误,而且还修改成功了(当然修改enumerable的值还是会导致错误的)。

再来看通过调用Object.defineProperty()方法添加的属性:

 1 var a = {
 2    name: \'A\',
 3    type: \'object\'
 4 }
 5 //修改直接在对象上定义的属性的值
 6 Object.defineProperty(a,\'style\',{
 7      configurable: false,
 8      value: \'jiangnan\'
 9 });
10 var b = Object.getOwnPropertyDescriptor(a,\'style\');
11 console.log(a.style);//jiangnan
12 console.log(b.configurable);//false
13 
14 Object.defineProperty(a,\'style\',{
15   writable: true,
16   value: \'to\'
17 });

看运行结果:

再调用Object.defineProperty()方法修改writable的特性,导致错误。

下面看Object.defineProperties()方法的用法:

 1 var a = {};
 2 Object.defineProperties(a,{
 3   name: {
 4     value: \'A\'
 5     //其余的三个特性未明确指定,默认值为false
 6   },
 7   type: {
 8     get: function() {return \'object\'}
 9     //set未指定,默认为undefined
10     //其余两个特性默认为false
11   }
12 });
13 console.log(a.type);//object
14 var b = Object.getOwnPropertyDescriptor(a,\'name\');
15 
16 console.log(b.writable);//false
17 
18 Object.defineProperty(a,\'name\',{
19   writable: true,
20  });

运行结果:

以上就是关于对象属性特性的内容。

以上是关于ECMAScript 5中属性的特性值的主要内容,如果未能解决你的问题,请参考以下文章

ECMAScript中有两种属性:数据属性和访问器属性。

译ECMAScript 2016, 2017, 2018 新特性之必读篇

javascript中的属性类型

一小时学会ECMAScript6新特性

ECMAScript 2017(ES8)特性概述

Javascript之对象的属性类型