你必须了解的JavaScript中的属性描述对象详解(上)
作者:程序小猿2
属性描述对象
JavaScript其实支持多种编程范式的,包括函数式编程和面向对象编程:
- JavaScript冲的对象被设计为一组属性无序集合,像是一个嘻哈表,由key和value组成;
- key是一个标识符名称,value可以是任意类型,也可以是其他对象或者函数类型;
- 如果值是一个函数,那么我们可以称之为对象的方法。
所以,属性描述对象的概念就为:JavaScript提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。
下面是属性描述对象的一个例子。
{ value:123, writable:false, enumerable:true, configurable:false, get:undefined, set:undefined }
属性描述对象提供六个元属性。
value
:value
是该属性的属性值,默认为undefined
。writable
:writable
是一个布尔值,表示属性值(value)是否可改变(即是否可改写),默认为true
。enumerable
:enumerable
是一个布尔值,表示该属性是否可遍历,默认为true
。如果设为false
,会使得某些操作(比如for...in
循环、Object.keys()
)跳过该属性。configurable
:configurable
是一个布尔值,表示可配置性,默认为true
。如果设为false
,将阻止某些操作改写属性,比如无法删除该属性,也不得改变该属性的属性描述对象(value
属性除外)。也就是说,configurable
属性控制了属性描述对象的可写性。get
:get
是一个函数,表示该属性的取值函数(getter),默认为undefined
。set
:set
是一个函数,表示该属性的存值函数(setter),默认为undefined
。
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor()
方法可以获取属性描述对象。他的第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。
var obj = (p:'a'}; Object.getOwnPropertyDescriptor(obj,'p') //Object{ value:"a", // writable:true, // enumerable:true, // configurable:true }
上面代码中,Object.getOwnPropertyDescriptor()
方法获取obj.p
的属性描述对象。
注意,Object.getOwnPropertyDescriptor()
方法只能用于对象自身的属性,不能用于继承的属性。
var obj = {p:'a'); Object.getOwnPropertyDescriptor(obj,'toStrng') //undefined
上面代码中,toString
是obj
对象继承的属性,Object.getOwnPropertyDescriptor()
无法获取。
Object.getOwnPropertyNames()
Object.getOwnPropertyNames
方法返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。
var obj = Object.defineProperties({},{ p1:{value:1,enumerable:true}, p2:{value:2,enumerable:false} }); Object.getOwnPropertyNames(obj) //["p1","p2"]
上面代码中,obj.p1
是可遍历的,obj.p2
是不可遍历的。Object.getOwnPropertyNames
会将它们都返回。
这跟Object.keys
的行为不同,Object.keys
只返回对象自身的可遍历属性的全部属性名。
Object.keys([])//[] Object.getOwnPropertyNmaes([])//['length'] Object.keys(Object.prototype)// [] Object.getOwnPropertyNames(Object.prototype) //['hasOwmProperty' // 'valueOf', // 'constructor', // 'toLocaleString', // 'isPrototypeOf', // 'propertyIsEnumerable', // 'toString']
上面代码中,数组自身的length
属性是不可遍历的,Object.keys
不会返回该属性。第二个例子Object.prototype
也是一个对象,所有实例对象都会继承它,它自身的属性都是不可遍历的。
Object.defineProperty(),Object.defineProperties()
Object.defineProperty()
方法允许通过属性描述对象,定义或修改一个属性,然后返回修改后的对象,它的用法如下。
Object.defineProperty(object,propertyName,attributesObject)
Object.defineProperty
方法接受三个参数,依次如下。
- object:属性所在的对象
- propertyName:字符串,表示属性名
- attributesObject:属性描述对象
举例来说,定义obj.p
可以写成下面这样。
var obj = Object.defineProperty({},'p',{ value:123, writable:false, enumerable:true, configurable:false }); obj.p //123 obj.p = 246; obj.p //123
上面代码中,Object.defineProperty()
方法定义了obj.p
属性。由于属性描述对象的writable
属性为false
,所以obj.p
属性不可写。注意,这里的Object.defineProperty
方法的第一个参数是{}
(一个新建的空对象),p
属性直接定义在这个空对象上面,然后返回这个对象,这是Object.defineProperty()
的常见用法。
如果属性已经存在,Object.defineProperty()
方法相当于更新该属性的属性描述对象。
如果一次性定义或修改多个属性,可以使用Object.defineProperties()
方法。
var obj = Object.defineProperties({},{ p1:{value:123,enumerable:true}, p2:{value:'abc',enumerable:true}, p3:{get:function(){return this.p1 + this.p2}, enumerable:true, configurable:true } }); obj.p1 //123 obj.p2 //"abc" obj.p3 //"123abc"
上面代码中,Object.defineProperties()
同时定义了obj
对象的三个属性。其中,p3
属性定义了取值函数get
,即每次读取该属性,都会调用这个取值函数。
注意,一旦定义了取值函数get
(或存值函数set
),就不能将writable
属性设为true
,或者同时定义value
属性,否则会报错。
var obj = {}; Object.defineProperty(obj,'p',{ value:123, get:function(){return 456;} }); //TypeError: Invalid property. // A property cannot both have accessors and be writable or have a value Object.defineProperty(obj,'p'{ writable:true, get:function(){return 456;} }); // TypeError: Invalid property descriptor. // Cannot both specify accessors and a value or writable attribute
上面代码中,同时定义了get
属性和value
属性,以及将writable
属性设为true
,就会报错。
Object.defineProperty()
和Object.defineProperties()
参数里面的属性描述对象,writable
、configurable
、enumerable
这三个属性的默认值都为false
。
var obj = {}; Object.defineProperty(obj,'foo',{}); Object.getOwnPropertyDescriptor(obj,'foo') //{ // value:undefined, // writable:false, // enumerable:false, // configurable:false //}
上面代码中,定义obj.foo
时用了一个空的属性描述对象,就可以看到各个元属性的默认值。
Object.prototype.propertyIsEnumerable()
实例对象的propertyIsEnumerable()
方法返回一个布尔值,用来判断某个属性是否可遍历。注意,这个方法只能用于判断对象自身的属性,对于继承的属性一律返回false
。
var obj = {}; obj.p = 123; obj.propertyIsEnumerable('p') //true obj.propertyIsEnumerable('toString') //false
上面代码中,obj.p
是可遍历的,而obj.toString
是继承的属性。
到此这篇关于你必须了解的JavaScript中的属性描述对象详解(上)的文章就介绍到这了,更多相关JavaScript属性描述对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!