ECMA中有两种属性:数据属性
和访问器属性
一、数据属性
数据属性,其特性主要有:
1)[[Configurable]]
,表示一个属性是否可配置的,当这个值为true的时候,那么可以有以下行为:
- 能够通过
delete
删除属性 - 能够修改属性的特性
- 能够把属性类型改为
访问器属性
类型
2)[[Enumerable]]
表示一个属性是否可枚举的:即能否通过for-in
循环返回属性
3)[[Writable]]
表示能否修改一个属性的值
4)[[Value]]
数据值的存储位置
要修改这些特性,需要使用ES5中的Object.defineProperty()
方法,这个方法接受三个参数,分别为:被修改属性所在的对象,被修改属性的名称,描述符对象
而其中描述符对象必须是configurable
、writable
、enumerable
、value
中的一或多个。
注意:在一个对象里直接定义的属性,其configurable
、writable
、enumerable
默认情况下都是true
,而通过Object.defineProperty()
定义的属性,默认情况下则都是false
以下进行试验,有:
var obj = {}
Object.defineProperty(obj, 'name', {
value: 'RuphiLau'
});
obj.name; // 'RuphiLau'
obj.name = 'Ruphi';
obj.name; // 'RuphiLau'
Object.keys(obj); // []
delete obj.name; // false
obj.name; // 'RuphiLau'
一旦把一个属性的特性设置为不可配置的,那么它就再也不能变为可配置的了,这种情况下,再次调用Object.defineProperty()
设置任何属性都会报错,如:
var obj = {}
Object.defineProperty(obj, 'name', {
configurable: false,
value: 'RuphiLau'
});
// 以下代码会报错
Object.defineProperty(obj, 'name', {
value: '123'
});
而在configurable
为true
的情况下,就可以多次调用来进行修改了
二、访问器属性
访问器属性不包含属性的值,它的主要特性有:
1)[[Configurable]]
2)[[Enumerable]]
3)[[Get]]
设置getter函数
4)[[Set]]
设置setter函数
访问器属性的特性需要通过Object.defineProperty()
进行修改,而其中对于getter和setter,它们 内部的this指向属性所在的对象
IE8首先实现了Object.defineProperty(),但是IE8只是部分实现,它的使用带有以下的限制:只能在DOM对象上使用该方法,且只能创建访问器属性
还有两个非标准方法也可以实现getter和setter,这就是由火狐浏览器首先引入的__defineGetter__()
和__defineSetter__()
,使用如:
var obj = {
_birthYear: 1996
}
obj.__defineGetter__('age', function() {
return (new Date()).getFullYear() - this._birthYear;
});
obj.__defineSetter__('age', function(newVal) {
this._birthYear = (new Date()).getFullYear() - newVal;
});
三、定义多个属性
ES5还提供了Object.defineProperties()
方法,用于一次性定义多个属性,如:
var obj = {};
Object.defineProperties(obj, {
prop1: {
// 描述符1
},
prop2: {
// 描述符2
}
// ...
});
四、读取属性的特性
可以使用Object.getOwnPropertyDescriptor(obj, propName)
方法来获取一个属性各项特性的设置情况。
对于数据属性
,它返回的对象里包含有如下属性:
configurable
enumerable
writable
value
对于访问器属性
,它返回的对象里包含有如下属性:
configurable
enumerable
get
set