基础 const
在 JavaScript 中使用 const
关键字声明变量的主要目的是为了创建一个常量,即一个不可重新赋值的变量。这意味着一旦你给 const
变量赋值后,就不能再次给它赋新的值。
在函数内部使用 const
可以确保变量在其作用域内保持不变,这样可以防止在后续逻辑中意外修改该变量,从而减少潜在的错误和提高代码的可读性和稳定性。
然而,需要注意的是,虽然 const
变量的引用不能被改变,但如果该变量是一个对象或数组,那么对象或数组的内容是可以被修改的(也称为“浅层不可变性”)。例如:
function example() {
const myArray = [1, 2, 3];
// 下面的操作不会报错,因为虽然 myArray 的引用不变,但其内容可以更改
myArray.push(4);
console.log(myArray); // 输出:[1, 2, 3, 4]
const myObject = { name: 'Alice' };
// 同样,下面的操作也不会报错
myObject.name = 'Bob';
console.log(myObject); // 输出:{ name: 'Bob' }
}
如果需要确保对象或数组内容也不可变,可以使用更深度的冻结方法如 Object.freeze()
或 Immutable.js 等库来实现。
Object.freeze()
Object.freeze()
是 JavaScript 中的一个方法,用于冻结一个对象,使其变得不可变。一旦一个对象被冻结,就无法再添加新的属性、删除已有属性、修改其已有属性的值以及改变已有属性的可枚举性、可配置性和可写性。
下面是一个使用 Object.freeze()
的示例:
// 创建一个原始对象
let originalObject = {
name: "Alice",
age: 30,
address: {
city: "New York",
country: "USA"
},
sayHello: function() {
console.log("Hello, my name is " + this.name);
}
};
// 使用 Object.freeze() 冻结对象
originalObject = Object.freeze(originalObject);
// 尝试更改已冻结对象的属性
originalObject.name = "Bob"; // 这行代码不会有任何效果,name 仍然是 "Alice"
// 尝试添加新属性
originalObject.gender = "female"; // 这行代码也不会有任何效果,gender 不会被添加到对象中
// 尝试删除已有属性
delete originalObject.age; // 这行代码无效,age 属性仍然存在
// 尝试修改内部对象(注意:这里只是浅冻结,内部对象没有被冻结)
originalObject.address.city = "San Francisco"; // 这个操作会成功,因为address本身并未被冻结
console.log(originalObject); // 输出:
// { name: "Alice", age: 30, address: { city: "San Francisco", country: "USA" }, sayHello: [Function: sayHello] }
// 深度冻结的例子
function deepFreeze(obj) {
if (obj instanceof Object) {
Object.freeze(obj);
for (const key in obj) {
if (obj.hasOwnProperty(key) && obj[key] instanceof Object) {
deepFreeze(obj[key]);
}
}
}
}
// 对原始对象进行深度冻结
deepFreeze(originalObject);
// 现在尝试修改内部对象属性
originalObject.address.city = "Los Angeles"; // 因为进行了深度冻结,这个操作不会再有影响
在这个例子中,我们首先创建了一个对象 originalObject
,然后使用 Object.freeze()
方法将其冻结。之后尝试对冻结对象进行修改的操作都不会生效,但对于包含复杂数据结构(如嵌套对象)的情况,Object.freeze()
只能实现浅冻结,即只冻结最外层对象,若要深层冻结需递归调用 Object.freeze()
或者使用其他深冻结函数如上面定义的 deepFreeze()
函数。
deepFreeze
这段代码定义了一个名为 deepFreeze
的 JavaScript 函数,用于递归地深度冻结一个对象及其所有嵌套的可枚举对象属性。下面是详细注释:
// 定义一个名为 deepFreeze 的函数,它接受一个参数 obj(需要被冻结的对象)
function deepFreeze(obj) {
// 首先检查传入的参数是否是一个对象实例(包括数组、函数等也是对象),如果不是则直接返回,无需处理
if (obj instanceof Object) {
// 对传入的对象应用 Object.freeze 方法进行浅冻结
// 这一步会使得 obj 不可扩展(不能添加新的属性),且其已有属性变为不可配置和不可写
Object.freeze(obj);
// 遍历 obj 的所有可枚举属性(不包括原型链上的属性)
for (const key in obj) {
// 检查当前遍历到的属性是否是 obj 自身拥有的(而不是继承自原型链)且该属性值也是一个对象
if (obj.hasOwnProperty(key) && obj[key] instanceof Object) {
// 如果满足条件,则对这个嵌套的对象属性递归调用 deepFreeze 函数,确保深层对象也被冻结
deepFreeze(obj[key]);
}
}
}
}
通过这样的递归方式,deepFreeze
函数能够确保传递给它的任何具有嵌套结构的对象变得完全不可变,即任何级别的属性都无法再被添加、删除或修改。这对于那些希望数据始终保持不变或者在某些场景下防止意外修改的状态管理非常有用。