abbshr.github.io
abbshr.github.io copied to clipboard
盘点ES5核心内容——对象篇
ES5自从发布到现在已经有几年了,相比ES3确实增加了不少很赞的东西。可是大部分人还没接触到它非常棒的特性,下一代标准就要发布了。我想无论如何应该在ES6出台之前,回顾一下第五代提供的优秀特性。因为ES6的乱搞很有可能将JavaScript毁的面目全非。
Object
属性的getter
和setter
在ES5中属性值value可以用两个方法getter
和setter
替代。由这两个方法定义的属性称作存取器属性,而只有一个简单的值的属性被称为数据属性。当查询存取器属性时,自动调用getter方法,当为该属性设置值时,则调用setter方法。
如果存取器属性同时具有setter和getter方法,则该属性可读写;如果只有getter方法,赋值操作将会无效;如果只有setter方法,那么读取属性时返回undefined。
存取器属性也是可以被继承的。
定义存取器属性
字面量格式:
var obj = {
//普通的数据属性
data_prop: value,
//存取器属性
get accessor_prop() {
console.log("invoke 'getter' prop");
return ++this.data_prop;
},
set accessor_prop(value) {
console.log("invoke 'setter' prop");
this.data_prop = value;
}
};
通过Object的方法设置:
//为obj对象添加另一个只写存取器属性accessor2
Object.defineProperty(obj, "accesssor2", {
set: function (value) {
this.y = value;
}
});
属性的attributes
属性除了名称和值之外,还包括可写性、可枚举性、可配置性等特性。在ES3中所有的属性都是可写,可枚举,可配置的。然而这些特性均不可修改。
为了实现属性特性的查询和设置,ES5中定义了一个名为属性描述符的对象。对于数据属性,他的属性描述符对象包含value
、writable
、enumerable
和configurable
;而存取器属性的属性描述符对象包含get
、set
、enumerable
和configurable
。
ES5提供了Object.getOwnPropertyDescriptor
方法来获得某个对象的指定属性的属性描述符,ex:
//获取对象obj的x属性的属性描述符
Object.getOwnPropertyDescriptor(obj, 'x');
/* 返回
{
get: function(){...},
set: function(value){...},
enumerable: true,
configurable: true
}
*/
对于继承的属性或不存在的属性,该方法返回undefined。
正如前一个例子,可以调用Object.defineProperty
或Object.defineProperties
设置/增加属性的特性。
//传入要修改的对象,要修改/增加的属性名,属性描述符对象
Object.defineProperty(object, property, prop_desp);
//或批量设置属性,其中第二个参数是一个对象,包含要修改的属性及其描述符对象
Object.defineProperties(obj, {
x: {...},
y: {...},
z: {...}
});
这两个方法如果违反如下规则,将会抛出错误异常。来自_权威指南_:
- 如果对象 是 不可扩展的,则可以编辑已有的自有属性,但不能给他添加新属性。
- 如果属性是不可配置的,则不能修改它的可配置性和可枚举性。
- 如果存取器属性不可配置,则不能修改其getter和setter方法,也不能将它转换为数据属性。
- 如果数据属性不可配置,则不能将它转换为存取器属性。也不能将它的可写性从false改为true,但可以从true改为false。
- 如果数据属性既不可配置又不可写,则不能修改它的值。
- 如果数据属性可配置但不可写,则可以修改它的值。
对象的可扩展性
上面的列表中提到了可扩展性。对象的可扩展性用以表示是否可以给对象添加新属性。
ES5提供了查询和设置对象可扩展性的方法。一旦将对象变为不可扩展的,则不可能再转换回去了。
不过对象的可扩展性仅仅影响它本身:对于其原型中添加的属性,就算不可扩展的对象也仍然会继承他们。
Object.isExtensions
,Object.preventExtensions
方法可分别用来检测对象是否可扩展和转换为不可扩展。
对象上的新增特性主要就是这些,我们平常似乎不太关注上面讨论的这些问题,但是ES5偏偏增加了这些新的特性,可见其目是长远的,为开发大型app而做出规范,让开发者能够创建更接近内置原生对象的API。