什么是Object.freeze
Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;
- 冻结了一个对象则不能向这个对象添加新的属性
- 不能删除已有属性
- 不能修改该对象已有属性的可枚举性、可配置性、可写性,
- 不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改
freeze() 返回和传入的参数相同的对象
作用
Object.freeze()是ES5新增的特性,可以冻结一个对象,防止对象被修改。
vue 1.0.18+对其提供了支持,对于data或vuex里使用freeze冻结了的对象,vue不会做getter和setter的转换。
如果你有一个巨大的数组或Object,并且确信数据不会修改,使用Object.freeze()可以让性能大幅提升。在我的实际开发中,这种提升大约有5~10倍,倍数随着数据量递增。
Object.freeze基本使用
var obj = {
name:'alley',
age:19,
sex:'男'
}
obj.__proto__.habit = '运动';
Object.freeze(obj);
// 不能添加新属性
obj.address = '北京'
console.log(obj) // {name: "alley", age: 19, sex: "男"}
// 不能删除原有属性
delete obj.age
console.log(obj) // {name: "alley", age: 19, sex: "男"}
// 不能修改已有属性的值
obj.name = 'dy_alley'
console.log(obj) // {name: "alley", age: 19, sex: "男"}
// 不能修改原型
obj.__proto__ = '随便什么值'
console.log(obj.__proto__) // {habit: "运动", constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, …}
// 不能修改已有属性的可枚举性、可配置性、可写性
Object.defineProperty(obj,'name',{ // TypeError: Cannot redefine property: address
enumerable: false,
configurable: false,
writable: true
})
冻结数组
var arr = [1,2,3,4,5,6];
Object.freeze(arr);
arr[0] = 'alley';
console.log(arr); // [ 1,2,3,4,5].
深度冻结
Object.freeze只能进行浅冻结,如果对象里面有对象的情况下则无法冻结
var obj = {
name:'alley',
info: {
age:19,
sex:'男'
}
}
Object.freeze(obj);
obj.name = 'dy_alley';
obj.info.age = 20;
console.log(obj); // {name:'alley',info:{age:20,sex:'男'}};
通过递归来进行深度冻结
function deepFreeze(obj) {
/*
Object.getOwnPropertyNames()与Object.keys()的区别:
Object.getOwnPropertyNames返回的是对象中所有自己的属性;
Object.keys(obj)则返回的对象中所有自己的属性,也就是属性下的 enumerable: true 的属性
const obj = {};
Object.defineProperties(obj, {
name: {enumerable: true, value: 'alley'},
age: {enumerable: false, value: 25},
})
console.dir(Object.keys(obj))
console.dir(Object.getOwnPropertyNames(obj))
输出
> Array ["name"]
> Array ["name", "age"]
*/
var propsNames = Object.getOwnPropertyNames(obj);
propsNames.forEach((item)=>{
var props = obj[item];
if(props instanceof Object && props !==null) {
deepFreeze(props);
}
})
return Object.freeze(obj);
}
获取对象是否冻结
Object.isFrozen(obj)
Object.freeze原理
模拟Object.freeze原理主要用到了2个方法, Object.definedProperty()、Object.seal()
Object.definedProperty方法可以定义对象属性的特性
Object.seal 可以让对象不能被扩展