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'哟。