前文《防止浏览器控制台修改网页数据与函数的方法》给出了几个解决方法,需要对对象的每个属性或函数使用Object.defineProperty()配置其元特性configurable、enumerable、writable等。显然,这些操作缺乏灵活、不够实用、不能通用。
1、javascript对象的元特性
javascript对象的成员(数据或函数)均有一组元特性,约束成员的是否可配置(configurable)、可枚举(enumerable)、可改写(writable),以及提供value值和getter/setter读写器。一旦configurable为false,那么不能重定义其他的特性(writable除外,仍然可以由true改为false)。如果configurable为true,即使wrtiable为false,仍然可以通过Object.defineProperty()或Reflect.defineProperty()函数修改其value(此时不能通过类似obj.val = 1的方式修改其值)。
定义或修改元特性的语法如下:
Object与Reflect两个同名方法的区别在于:前者定义成功返回对象、失败抛出异常;后者成功返回true、失败返回false。另一个区别是,Reflect支持的最低版本是ES6(与Proxy一样)。
2、保护window和对象(以String.prototype为例)上新增的属性和函数
ES6中的Proxy类和Reflect类提供了通用、一致的便捷方法,只需要给被保护的对象(如window对象、String.prototype原型、String构造函数等)关联一个代理对象,在代理对象上新增属性或函数,就可以自动配置其元特性{configurable: false, enumerable: true, writable: false},从而保护数据(属性值)或函数被删除或修改。
下面代码是一个关联window对象和String.prototype原型的两个代理类,分别增加其函数sayOk(),然后修改函数定义,结果是:修改后的函数无效。