一、为什么需要引入防篡改对象?
1.
为什么?JavaScript 共享的本质一直是开发人员心头的痛,因为任何对象都可以被在同一环境中运行的代码修改。
2.
解决:我们可以手工设置每个对象属性的
[[Configurable]]
、
[[Writable]]
、
[[Enumerable]]
、
[[Value]]
、
[[Get]]
以及
[[Set]]
特性,同样我们可以设置对象的行为。
一、不可扩展的对象
1.
默认情况下,所有对象都是可以扩展的。也就是说,任何时候都可以向对象中添加属性和方法
var o = {
name :
"zhang"
}
o.age =
23
;
alert(o.age); //
23
2.
使用Object.preventExtensions()方法可以改变这个行为,让你不能再给对象添加属性和方法。
var o = {
name :
"zhang"
}
alert(Object.isExtensible(o)); //
true
Object.preventExtensions(o);
o.age =
23
;
alert(o.age); // undefined
alert(Object.isExtensible(o)); //
false
二、密封的对象
密封对象不可扩展,而且已有成员的
[[Configurable]]
特性将被设置为
false
。这就意味着不能删除属性和方法,因为不能使用Object.defineProperty()把数据属性修改为访问器属性,或者相反。属性值是可以修改的。
var o = {
name :
"zhang"
}
// alert(Object.isExtensible(o)); //
true
// alert(Object.isSealed(o)); //
false
// 不能添加属性和方法
Object.seal(o);
o.age =
23
;
// alert(o.age); // undefined
// 不能删除属性
delete o.name;
// alert(o.name); // zhang
// 可以修改已有属性的值
o.name =
"li"
;
alert(o.name);
alert(Object.isExtensible(o)); //
false
alert(Object.isSealed(o)); //
true
三、冻结的对象
冻结的对象既不可扩展,又是密封的,而且对象数据属性的
[[Writable]]
特性会被设置为
false
。如果定义
[[Set]]
函数,访问器属性仍然是可写的。
var o = {
name :
"zhang"
}
// alert(Object.isExtensible(o)); //
true
// alert(Object.isSealed(o)); //
false
// alert(Object.isFrozen(o)); //
false
// 不能添加属性和方法
Object.freeze(o);
o.age =
23
;
// alert(o.age); // undefined
// 不能删除属性
delete o.name;
// alert(o.name); // zhang
// 不可以修改属性
o.name =
"li"
;
// alert(o.name);
alert(Object.isExtensible(o)); //
false
alert(Object.isSealed(o)); //
true
alert(Object.isFrozen(o)); //
true