如何创建一个不可变的JavaScript对象

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

在面向对象和函数式编程中,不可变对象其状态在创建后无法修改的对象。这与可变对象形成对比,可变对象创建后可以修改。

在某些情况下,即使某些内部使用的属性发生变化,对象也被认为是不可变的,但从外部角度来看,对象的状态似乎没有变化。

字符串和其他具体对象通常表示为不可变对象,以提高面向对象编程的可读性和运行时效率。不可变对象也很有用,因为它们本质上是线程安全的。其他好处是它们比可变对象更易于理解和推理,并提供更高的安全性。

在JavaScript中,所有原始类型(Undefined、Null、Boolean、Number、BigInt、String、Symbol)都是不可变的,但自定义对象通常是可变的。

我们可以通过使用freeze()seal()方法来实现不可变对象。

JavaScript 中创建对象并将其分配给变量时,它不保存对象的值。这个变量只有对我们创建的对象的引用。

例如,如果我们创建一个对象poi,将其分配给另一个变量 pubPoi,我们将复制poi的引用,而不是值。因此,如果我们对pubPoi进行更改,也会修改poi值。

示例如下:

var poi = { 
   name: "hotel", 
   address: "beijing", 
};
var pubPoi= poi;
pubPoi.name = "scenic";
console.log(poi);
复制代码

Object.freeze()

Object.freeze()方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。

此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

示例如下:

var poi = { 
   name: "hotel", 
   address: "beijing", 
};

Object.freeze(poi);

poi.name = "test";
// Throws an error in strict mode

console.log(poi.name);
// expected output: hotel
复制代码

注意:

1.Object.freeze() 方法不会影响嵌套对象,如果需要冻结嵌套对象并使其不可变,则需要遵循递归方法逐级冻结。

2.Object.isFrozen()方法可以判断一个对象是否被冻结。

Object.seal()

Object.seal() 是另一种使对象不可变的方法。但是,它和 freeze() 有点不同。Object.seal() 仅保护对象不添加和删除属性。它允许更新现有属性。

var poi = { 
   name: "hotel", 
   address: "beijing", 
};

// 冻结
Object.seal(poi);
// 添加属性
poi["state"] = 0;
// 删除属性
delete poi["name"];
// 更新属性
poi.name = "scenic";

console.log(poi);
复制代码

对象添加和删除属性失败。但是,名称属性可以更新。

注意:

1.可以使用 isSealed() 方法来确认对象的密封状态。

2.Object.seal() 还具有类似于 Object.freeze() 的浅密封行为。所以需要一个递归策略来密封嵌套对象。

3.除了这2个方法之外,我们还可以使用Object.preventExtensions()方法,只防止向对象添加新的属性。

const 关键字不会使对象不可变

使用 const 关键字创建对象时,它只会阻止我们重新分配值。但是,我们可以更新、添加和删除创建的对象的属性。

const poi = { 
   name: "hotel", 
   address: "beijing", 
};
poi.name = "scenic";
delete poi["address"];
poi["state"] = 0;

console.log(poi);
复制代码

const关键字只提供了赋值的不变性。它并不提供值的不可更改性。

猜你喜欢

转载自juejin.im/post/7083300399565766669