前言
众所周知,在JavaScript
中我们使用const
声明一个常量时,一旦声明后就不能再重新赋值。但如果是对象或者是数组的属性与元素是可以被修改的。
那么怎么让const
定义的对象的属性也不能被修改呢?? 太简单了,下面会区别情况进行讲解与演示。
基本示例
其实很简单就看你有没有想到了,主要还是考验对API
的运用是否熟练,我们只需要结合使用Object.freeze()
方法就可以实现了,Object.freeze()
可以冻结对象,但只能冻结第一层属性。
因此我们先看看一层的对象示例
<html lang="zh">
<head>
<script>
const testobj = {
name: "天天鸭",
age: 88,
};
Object.freeze(testobj);
// 添加
testobj["newgen"] = "new天";
console.log("添加属性:", testobj.newgen);
// 删除
delete testobj.age;
console.log("删除属性:", testobj.age);
// 修改
testobj.name = "月月鸭";
console.log("修改属性:", testobj.name);
</script>
</head>
<body>
您好,我是天天鸭的示例
</body>
</html>
先用const
结合Object.freeze()
后对其进行增删改操作,下面看看对应的打印效果
看效果可以知道增删改都不会生效并且不会输出任何错误,并且如果是添加会输出undefined
。
注意: 如果是严格模式会报错,如下图片所示。
在Vue框架中示例
如果在Vue3
框架演示呢,你们觉得会有什么区别不???
下面直接上一个例子再说吧
<template>
<div></div>
</template>
<script setup>
const testobj = {
name: "天天鸭",
age: 88,
};
Object.freeze(testobj);
// 添加
testobj["newgen"] = "new天";
console.log("添加属性:", testobj.newgen);
// 删除
delete testobj.age;
console.log("删除属性:", testobj.age);
// 修改
testobj.name = "月月鸭";
console.log("修改属性:", testobj.name);
</script>
在Vue3
中先用const
结合Object.freeze()
后对其进行增删改操作,再看看下面打印出来的效果
啊这....怎么来到这里就直接报错了呢??? 你们知道为什么不
其实原因有二
一、是
Vue
在开发模式下会默认使用严格模式,从而会导致报错。二、是因为与
Vue
框架的响应式和生命周期相关的原因,Vue
的响应式机制会对对象进行依赖收集处理,从而实现响应式效果。当我们用Object.freeze
冻结时,Vue
会无法执行这些处理,因为已经冻结不可扩展了。
层级复杂的对象
我们日常使用对象处理数据的情况下不可能都是一层的简单结构,如果是层级很复杂的树状结构呢??毕竟Object.freeze()
只能冻结一层。
那当然是用递归了,看看下面例子
<html lang="zh">
<head>
<script>
function deepObjFreeze(obj) {
// 如果已经是冻结的
if (Object.isFrozen(obj)) {
return obj;
}
// 获取所有属性
const keys = Object.keys(obj);
// 冻结每个
keys.forEach((key) => {
const value = obj[key];
if (value && typeof value === "object" && !Object.isFrozen(value)) {
deepObjFreeze(value);
}
});
// 冻结当前
return Object.freeze(obj);
}
const testObj = {
name: "天天鸭",
age: 88,
details: {
age: 25,
gender: "new天",
},
};
const frozenObj = deepObjFreeze(testObj);
// 尝试修改属性
frozenObj.name = "new名";
frozenObj.details.age = 30;
console.log(frozenObj);
</script>
</head>
<body>
您好,我是天天鸭的示例
</body>
</html>
递归冻结后我们再去修改里面的属性,效果打印出来如下所示,不受任何影响。
小结
突然灵感一来,想起这个很考验基本功的小问题,没有难度,就是考我们对Object.freeze()
方法的熟悉和结合需求的灵活性。
好啦文章这到这里,如果哪里写的不对或者有更好的建议欢迎指出哦。