【发布时间】:2022-11-11 18:53:19
【问题描述】:
我正在尝试为 React 应用程序使用带有私有字段的 JS 类(因为我仍然觉得到处使用裸 Object 实例很奇怪)。 React 使用不可变状态的概念,因此我必须克隆我的对象才能更改它们。我正在使用私有字段 - 使用 getter 和 setter 来访问它们。我遇到的问题是私有字段不会在 Firefox、Chrome 或 Node.js 中被克隆。令人讨厌的是,我的 React 项目的 Jest 设置出现了误报,该代码在单元测试中按预期工作。
有没有办法解决这个问题?否则,看起来我必须放弃我的一些(感知的)封装安全性并改用下划线前缀的“私有”字段。
这是我的克隆功能:
const objclone = obj => {
const cloned = Object.assign(
Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj),
),
obj,
);
return cloned;
};
这会克隆 getter 和 setter 以及对象属性,并且在我使用私有字段之前似乎运行良好。
例子:
class C {
#priv;
constructor() {
this.#priv = 'priv-value';
}
get priv() { return this.#priv; }
}
const obj = new C();
console.log("obj.priv", obj.priv);
const cloned = objclone(obj);
console.log("cloned.priv", cloned.priv);
尝试访问 cloned.priv 时显示的错误消息:
火狐:
未捕获的类型错误:无法访问私有字段或方法:对象不是正确的类
铬和节点:
未捕获的类型错误:无法从类未声明的对象中读取私有成员#priv
【问题讨论】:
-
如果您的所有私有字段都有 getter 和 setter,那么无论如何您都没有任何封装安全性。
-
a)
Object.create不创建私有插槽,您需要为此调用构造函数 b) 您的Example类没有.priv的设置器 c)Object.assign不复制继承的、不可枚举的属性 -
我省略了 setter 以保持代码紧凑。添加时它不会改善事情。您关于封装的陈述对于简单的 getter 和 setter 来说是正确的,但在某些用例中,肯定会想要在其中做更多的事情。根据 IDE,它也可能在代码导航方面有所不同。
-
私有字段是私有的。如果您可以使用函数复制它们,它们就不会是私有的。
-
到目前为止,我得到的是:突然 JS 决定实施适当的 OOP,这是我不能(也不应该)使用 JS 工具克隆的一件事。我必须以传统方式做事,使用复制构造函数(这只是一个对 JS 没有特殊意义的类方法) - 编辑:实际上是克隆函数。或者......我将只使用下划线约定,并希望如果有人试图访问它们,它会尖叫“错误代码”。一直以来,
class仍然是下面的对象,除了私有字段之外没有什么特别的......除非转译器没有实现正确的语义。正确的?
标签: javascript clone private es6-class class-fields