abbshr.github.io icon indicating copy to clipboard operation
abbshr.github.io copied to clipboard

盘点ES5核心内容——对象篇

Open abbshr opened this issue 10 years ago • 0 comments

ES5自从发布到现在已经有几年了,相比ES3确实增加了不少很赞的东西。可是大部分人还没接触到它非常棒的特性,下一代标准就要发布了。我想无论如何应该在ES6出台之前,回顾一下第五代提供的优秀特性。因为ES6的乱搞很有可能将JavaScript毁的面目全非。

Object

属性的gettersetter

在ES5中属性值value可以用两个方法gettersetter替代。由这两个方法定义的属性称作存取器属性,而只有一个简单的值的属性被称为数据属性。当查询存取器属性时,自动调用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中定义了一个名为属性描述符的对象。对于数据属性,他的属性描述符对象包含valuewritableenumerableconfigurable;而存取器属性的属性描述符对象包含getsetenumerableconfigurable

ES5提供了Object.getOwnPropertyDescriptor方法来获得某个对象的指定属性的属性描述符,ex:

    //获取对象obj的x属性的属性描述符
    Object.getOwnPropertyDescriptor(obj, 'x');

    /* 返回 
    {
        get: function(){...}, 
        set: function(value){...}, 
        enumerable: true, 
        configurable: true
    }
    */

对于继承的属性或不存在的属性,该方法返回undefined。

正如前一个例子,可以调用Object.definePropertyObject.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。

abbshr avatar Mar 30 '14 10:03 abbshr