JS 中的 const 📦、seal 🤐、freeze ❄️ 和 immutability 🤓
AWS GenAI 直播!
不可变数据一旦创建就无法更改。大多数情况下,这会使代码更简洁,错误更少。这就是为什么不可变数据结构经常成为热门话题的原因。让我们看看用 JS 能实现什么!
你可能会说, const肯定赢了,因为这样你就能创建常量了,对吧?嗯……不对。使用 const,你创建的变量无法被重新赋值。
因此下面的代码将无法工作:
const x = "Dog"
x = "Cat" // crashes with "Uncaught TypeError: Assignment to constant variable."
当然,使用let和var可以重新分配变量。
那么,为什么 const 不是不可变的呢?让我们看看当我们使用对象而不是原始值时会发生什么。
const obj = { name: "Doggo" }
// let's change a property
obj.name = "Kitty"
// and add one
obj.animal = "cat"
console.log(obj) // {name: "Kitty", animal: "cat"}
// reassigning will not work
obj = { name: "Birdo" } // crashes with "Uncaught TypeError: Assignment to constant variable."
因此,我们仍然可以添加和更改对象的属性。但是 Object 中有一个seal
方法和一个freeze
方法,它们的作用基本上与它们的名称完全一致。我们先来看看seal:
const obj = { name: "Doggo" }
// let's seal our object
Object.seal(obj)
// let's change the property again
obj.name = "Kitty"
// and also add one again
obj.animal = "cat"
console.log(obj) // {name: "Kitty"}
那么这里发生了什么?name属性可以更改,但animal属性却无法添加。这正是seal的作用:它阻止向对象添加属性。现有属性仍然可以更改。
冻结方法可以防止更改以及添加/删除属性。
const obj = { name: "Doggo" }
// let's freeze our object
Object.freeze(obj)
// let's change the property again
obj.name = "Kitty"
// and also add one again
obj.animal = "cat"
console.log(obj) // {name: "Doggo"}
好吧,那么将const与Object.freeze结合使用就能实现不可变性,对吗?嗯……还是不行。freeze 方法并非所谓的深度冻结。这意味着,只有第一层对象真正被冻结;该对象内的其他对象不会被冻结。我们来看一个例子:
// we'll give the dog an owner, that also has a name (mine ;)
const obj = { name: "Doggo", owner: { name: "Ben" } }
// we'll again freeze the object
Object.freeze(obj)
// and this time we'll change the name of the owner
obj.owner.name = "Bla"
console.log(obj) // {name: "Doggo", owner: {name: "Bla"}}
为了真正实现不可变性,你可以创建一个深度冻结方法,递归地运行所有对象属性并冻结所有嵌套对象。如果你对此教程感兴趣,请告诉我!
想要提升 Web 开发能力?
🚀🚀🚀订阅我的每周✉️简报