JavaScript 对象的防篡改preventExtensions/seal/freeze
// 首先声明三个对象
const a = {v: 1};
const b = {v: 1};
const c = {v: 1};
/*
Object.preventExtensions() 方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
Object.seal() 方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
*/
Object.preventExtensions(a);
Object.seal(b);
Object.freeze(c);
/*
Object.getOwnPropertyDescriptors() 用来获取一个对象的所有自身属性的描述符(结构是否可改变, 是否可枚举, 属性是否可更改)。
* 1.configurable:表示能否通过delete删除此属性,能否修改属性的特性,或能否修改把属性修改为访问器属性,如果直接使用字面量定义对象,默认值为true;
* 2.enumerable: 表示该属性是否可枚举,即是否通过for-in循环或Object.keys()返回属性,如果直接使用字面量定义对象,默认值为true;
* 3.writable: 能否修改属性的值,如果直接使用字面量定义对象,默认值为true;
* 4.value: 该属性对应的值,默认为undefined。
* */
console.log(Object.getOwnPropertyDescriptors(a)); // => {v: {value: 1, writable: true, enumerable: true, configurable: true}}
console.log(Object.getOwnPropertyDescriptors(b)); // => {v: {value: 1, writable: true, enumerable: true, configurable: false}}
console.log(Object.getOwnPropertyDescriptors(c)); // => {v: {value: 1, writable: false, enumerable: true, configurable: false}}
// 下面开始修改对象
a.v = 2;
a.k = 0;
b.v = 2;
b.k = 0;
c.v = 2;
c.k = 0;
console.log(a); // => {v: 2} // 可修改不可添加
console.log(b); // => {v: 2} // 可修改不可添加
console.log(c); // => {v: 1} // 不可修改不可添加
/*
Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
* */
console.log(Object.isExtensible(a)); // => false
console.log(Object.isExtensible(b)); // => false
console.log(Object.isExtensible(c)); // => false
/* 均为不可扩展 */
// 再来使用delete操作对象
delete a.v;
delete b.v;
delete c.v;
console.log(a); // => {} // 可删除
console.log(b); // => {v: 2} // 不可删除
console.log(c); // => {v: 1} // 不可删除
/*
结论
* preventExtensions 可删除和修改源属性,不可添加新属性
* seal 可修改但是不可删除源属性,不可添加新属性
* freeze 不可修改和源属性,不可添加新属性
* !* 三者都不可扩展新属性
* */
为之则易,不为则难。