使用Proxy对象创建不可变的JavaScript对象

对象的可变性及其与const关键字的关系是开发人员经常遇到的问题。通常情况下,在寻找使对象不可变的方法时,Object.freeze()会被提出作为解决方案。我们之前已经探讨过这种方法,并详细介绍了深度冻结的解决方案。您可以在这篇文章中了解更多信息。

虽然Object.freeze()是更直接的方法,但它并不总是最佳解决方案。特别是在处理大量对象嵌套或对象生命周期很短的情况下,使用Proxy对象可能更合适。下面是使用Proxy对象的示例:

const term = {
  id: 1,
  value: 'hello',
  properties: [{ type: 'usage', value: 'greeting' }],
};

const immutable = obj =>
  new Proxy(obj, {
    get(target, prop) {
      return typeof target[prop] === 'object'
        ? immutable(target[prop])
        : target[prop];
    },
    set() {
      throw new Error('This object is immutable.');
    },
  });

const immutableTerm = immutable(term);
const immutableProperty = immutableTerm.properties[0];

immutableTerm.name = 'hi';            // 报错:该对象是不可变的。
immutableTerm.id = 2;                 // 报错:该对象是不可变的。
immutableProperty.value = 'pronoun';  // 报错:该对象是不可变的。

虽然代理并不常见,但这段代码应该不难理解。其核心思想是使用处理程序通过set()陷阱来阻止对对象的变异。此外,您还可以使用get()陷阱来强制执行所有嵌套值的不可变性。这是通过检查值的类型并将代理应用于嵌套对象来实现的。

基本上就是这样。只需几行代码,您现在就可以防止对象的变异,无论其形状、嵌套程度或复杂性如何。