ECMAScript2015 对象扩展

    上篇文章学习和记录了Object.defineProperty的用法,主要是对属性的扩展定义。这次学习三个API,是关于对象操作的三个扩展。

    分别是下面三对,具体来讲讲它们的区别和联系以及用法。

    1. Object.freeze() / Object.isFrozen()
    2. Object.seal() / Object.isSealed()
    3. Object.preventExtensions() / Object.isExtensible

    Object.freeze() / Object.isFrozen()

    Object.freeze()是这三个里面最高级别。通过Object.freeze(obj)的obj,相当于已经冻结了:不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性的对象。

    也就是说这个对象不可以变了。

    1
    2
    3
    4
    5
    6
    7
    8
    var obj = {a:1,b:2};
    obj.c = 3;
    Object.freeze(obj);
    obj.d = 4; //不会抛出异常
    obj.d //undefined
    delete obj.c //false

    上述我们可以看到,虽然obj被冻结了,但是我们在它上面修改属性的时候,仍然是可以的,只是不会得到正确的值,不抱错。这很明显会对我们整体的代码造成影响,以后排查错误也不方便。所以我们需要定义’use strict’,在严格模式下,就可以报错啦。

    1
    2
    3
    4
    5
    'use strict'
    //TypeError: "c" is read-only
    obj.c = 0;
    Object.isFrozen(obj) //true

    然后我们可以定义Object.isFrozen来判断是否该对象被冻结了。


    Object.seal() / Object.isSealed()

    密封一个对象,并返回被密封后的对象。密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可以修改已有属性的值的对象。

    所以在Object.freeze的基础上,就是可以修改自己已经有了的属性。但是还是不能删除和添加。 也不能修改已有属性的可枚举,可写等特性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var obj = {a:1, b:2};
    Object.seal(obj);
    Object.isSealed(obj); // true
    obj.c = 3; //不抛出异常
    obj.c // undefined
    delete obj.b // false
    //已有属性可以变更值
    obj.b = 3;
    obj.b //3
    //TypeError: can't define property "[object Object]": Object is not extensible
    Object.defineProperty(obj,a,{
    value : 'r',
    writable : true,
    configurable : true
    })

    通过上面一些简单的例子,我们可以看到Object.freezeObject.seal的区别了。Object.freeze更加严格,Object.seal相当于封装好了这个对象,不准多一个,也不准少一个,但是你可以在这个里面更改原来已有的。


    Object.preventExtensions / Object.isExtensible

    阻止对象扩展,让一个对象变的不可扩展,也就是永远不能再添加新的属性。在没有这个之前,我们定义了一个对象,是可以进行无限制的扩展属性的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var obj = {a:1, b:2};
    obj.c = 3;
    Object.preventExtensions(obj);
    obj.d = 4; // 不抛出异常
    obj.d // undefined,不能扩展属性
    Object.isExtensible(obj); // false
    obj.a = 'a';
    obj.a // 'a',可以更改已有的属性
    delete obj.a //可以删除已有属性
    obj.a //删除后再添加也不行

    总结

    三者有类似的作用,但是用法很不同。可以通过这些API,对对象再进行更严谨的控制。这样代码的健壮性更好了。也更容易让我们发现错误,多人合作的时候也更不容易出错。但一定要记得写严格模式的'use strict'哟。