返回
数据不变,对象可改,优雅的 Immer
前端
2023-09-20 16:16:53
不可变数据是只读数据,一旦创建就不能再被改变。这与可变数据相反,可变数据可以被修改或更新。
追求不可变数据的主要原因是它可以帮助我们编写更可靠、更易于维护的代码。当我们使用不可变数据时,我们可以确信数据不会在我们的代码中意外更改。这可以帮助我们避免错误并使我们的代码更易于理解。
实现不可变数据
实现不可变数据的一种方法是使用对象冻结(Object.freeze())。然而,这只能冻结对象本身,而不能冻结对象中的属性。为了冻结对象中的所有属性,我们需要使用递归冻结(deep freeze)。
function deepFreeze(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
Object.freeze(obj);
for (const key of Object.keys(obj)) {
deepFreeze(obj[key]);
}
return obj;
}
另一种实现不可变数据的方法是使用代理(proxy)。代理是一个对象,它可以拦截对另一个对象的访问并修改对该对象的访问。我们可以使用代理来创建一个不可变的视图,它可以使我们对对象进行修改而不改变对象本身。
const obj = {
foo: 'bar',
baz: {
qux: 'quux'
}
};
const proxy = new Proxy(obj, {
set: function(target, property, value) {
throw new Error('Cannot set property ' + property + ' on immutable object');
}
});
proxy.foo = 'quux'; // Error: Cannot set property foo on immutable object
Immer
Immer 是一个 JavaScript 库,它提供了一种简单的方法来创建可变对象而不破坏不可变性。它使用代理来创建一个不可变的视图,它可以使我们对对象进行修改而不改变对象本身。
const obj = {
foo: 'bar',
baz: {
qux: 'quux'
}
};
const nextObj = produce(obj, draft => {
draft.foo = 'quux';
draft.baz.qux = 'corge';
});
console.log(obj); // { foo: 'bar', baz: { qux: 'quux' } }
console.log(nextObj); // { foo: 'quux', baz: { qux: 'corge' } }
在上面的示例中,我们使用 Immer 的 produce() 函数来创建一个不可变的视图。然后,我们可以在视图中对对象进行修改,而不会改变对象本身。
结论
Immer.js 是一个强大的库,它可以帮助我们编写更可靠、更易于维护的代码。通过使用 Immer.js,我们可以轻松地创建可变对象而不破坏不可变性。