个人随笔
目录
当前位置: 首页 JS JS防篡改对象
JS防篡改对象
2020-05-22 23:50:17
摘要:JS防篡改对象,不可扩展对象,密封对象,冻结对象

JavaScript 共享的本质一直是开发人员心头的痛。因为任何对象都可以被在同一环境中运行的代码修改。开发人员很可能会意外地修改别人的代码,甚至更糟糕地,用不兼容的功能重写原生对象。ECMAScript 5 致力于解决这个问题,可以让开发人员定义防篡改对象(tamper-proof object)。第6章讨论了对象属性的问题,也讨论了如何手工设置每个属性的[[Configurable]]、[[Writable]]、 [[Enumerable]]、[[Value]]、[[Get]]以及[[Set]]特性,以改变属性的行为。类似地,ECMAScript 5也增加了几个方法,通过它们可以指定对象的行为。不过请注意:一旦把对象定义为防篡改,就无法撤销了。

一、不可扩展对象

默认情况下,所有对象都是可以扩展的。也就是说,任何时候都可以向对象中添加属性和方法。例如,可以像下面这样先定义一个对象,后来再给它添加一个属性。

  1. var person = { name: "Nicholas" };
  2. person.age = 29;

即使第一行代码已经完整定义 person 对象,但第二行代码仍然能给它添加属性。现在,使用Object.preventExtensions()方法可以改变这个行为,让你不能再给对象添加属性和方法。例如:

  1. var person = { name: "Nicholas" };
  2. Object.preventExtensions(person);
  3. person.age = 29;
  4. alert(person.age); //undefined

在调用了 Object.preventExtensions()方法后,就不能给 person 对象添加新属性和方法了。在非严格模式下,给对象添加新成员会导致静默失败,因此person.age 将是 undefined。而在严格模式下,尝试给不可扩展的对象添加新成员会导致抛出错误。虽然不能给对象添加新成员,但已有的成员则丝毫不受影响。你仍然还可以修改和删除已有的成员。另外,使用 Object.istExtensible()方法还可以确定对象是否可以扩展。

  1. var person = { name: "Nicholas" };
  2. alert(Object.isExtensible(person)); //true
  3. Object.preventExtensions(person);
  4. alert(Object.isExtensible(person)); //false

二、密封的对象

ECMAScript 5 为对象定义的第二个保护级别是密封对象(sealed object)。密封对象不可扩展,而且已有成员的[[Configurable]]特性将被设置为 false。这就意味着不能删除属性和方法,因为不能使用 Object.defineProperty()把数据属性修改为访问器属性,或者相反。属性值是可以修改的。要密封对象,可以使用Object.seal()方法。

  1. var person = { name: "Nicholas" };
  2. Object.seal(person);
  3. person.age = 29;
  4. alert(person.age); //undefined
  5. delete person.name;
  6. alert(person.name); //"Nicholas"

在这个例子中,添加 age 属性的行为被忽略了。而尝试删除 name 属性的操作也被忽略了,因此这个属性没有受任何影响。这是在非严格模式下的行为。在严格模式下,尝试添加或删除对象成员都会导致抛出错误。

使用 Object.isSealed()方法可以确定对象是否被密封了。因为被密封的对象不可扩展,所以用Object.isExtensible()检测密封的对象也会返回 false。

  1. var person = { name: "Nicholas" };
  2. alert(Object.isExtensible(person)); //true
  3. alert(Object.isSealed(person)); //false
  4. Object.seal(person);
  5. alert(Object.isExtensible(person)); //false
  6. alert(Object.isSealed(person)); //true

三、冻结的对象

最严格的防篡改级别是冻结对象(frozen object)。冻结的对象既不可扩展,又是密封的,而且对象数据属性的[[Writable]]特性会被设置为 false。如果定义[[Set]]函数,访问器属性仍然是可写的。ECMAScript 5 定义的 Object.freeze()方法可以用来冻结对象。

  1. var person = { name: "Nicholas" };
  2. Object.freeze(person);
  3. person.age = 29;
  4. alert(person.age); //undefined
  5. delete person.name;
  6. alert(person.name); //"Nicholas"
  7. person.name = "Greg";
  8. alert(person.name); //"Nicholas"

与密封和不允许扩展一样,对冻结的对象执行非法操作在非严格模式下会被忽略,而在严格模式下会抛出错误。当然,也有一个 Object.isFrozen()方法用于检测冻结对象。因为冻结对象既是密封的又是不可扩展的,所以用 Object.isExtensible()和 Object.isSealed()检测冻结对象将分别返回 false和 true。

  1. var person = { name: "Nicholas" };
  2. alert(Object.isExtensible(person)); //true
  3. alert(Object.isSealed(person)); //false
  4. alert(Object.isFrozen(person)); //false
  5. Object.freeze(person);
  6. alert(Object.isExtensible(person)); //false
  7. alert(Object.isSealed(person)); //true
  8. alert(Object.isFrozen(person)); //true

对 JavaScript 库的作者而言,冻结对象是很有用的。因为 JavaScript 库最怕有人意外(或有意)地修改了库中的核心对象。冻结(或密封)主要的库对象能够防止这些问题的发生。

 340

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2