Javascript 中的私有字段不会出现在 JSON.stringify 中

Posted

技术标签:

【中文标题】Javascript 中的私有字段不会出现在 JSON.stringify 中【英文标题】:Private fields in Javascript don't show up in JSON.stringify 【发布时间】:2021-12-19 04:50:32 【问题描述】:

所以如果我写一个类如下

class Rectangle 
   #width;
   #height;
   constructor() 
      this.#width = 3;
      this.#height = 5; 
   



let rect = new Rectangle();

console.log(JSON.stringify(rect)); // returns 

它将返回一个空对象,完全忽略我所有的私有成员。 添加一个 toJSON 方法是可行的,但这变得非常麻烦。是否有任何内置方法可以轻松让我的私有字段显示在 JSON.stringify 中?还是我只需将每个成员都写入 toJSON 方法?

【问题讨论】:

一般情况下 - 尽可能不要尝试JSON.stringify instances,它们在与 JSON 之间进行转换很麻烦。如果您必须 使用私有字段,那么是的,您必须明确地将它们全部写出来。在可能的情况下更容易使用普通对象 IMO @CertainPerformance 这就是我害怕的。类和实例的使用在我目前正在开发的程序中非常有用,但它们给我带来的麻烦可能并不值得。感谢您的回复。 如果您希望JSON.stringify 访问私有字段,请不要使用它们!? 【参考方案1】:

避免写出所有成员的一种选择是在实例上拥有一个私有数据属性,然后序列化/反序列化该属性:

class Rectangle 
   #data;
   constructor(data) 
      this.#data = data;
   
   getWidth = () => this.#data.width;
   toJson = () => JSON.stringify(this.#data);

const r = new Rectangle( width: 1, height: 1 );
console.log(r.getWidth());
const stringified = r.toJson();
console.log(stringified);

const restructured = new Rectangle(JSON.parse(stringified));
console.log(restructured.getWidth());

【讨论】:

非常感谢您的回复。我也在考虑这样做。如果我想继续使用私人成员,这可能是最好的解决方案。我还想过在构造时将所有私有字段添加到对象中,然后每次使用 setter 时更新该对象,但这似乎也很痛苦。 您可能希望将它们从箭头函数更改为 function 关键字,以便它们具有正确的 this @MrMythical 他们已经有了正确的this。在类字段箭头函数中,this 将始终肯定引用该实例。您可以通过运行实时 sn-p 来亲自查看 - 按“运行代码 sn-p”。我更喜欢这里的箭头函数,因为它们很简洁(没有function,没有return 补充@CertainPerformance 所说的内容。与使用箭头运算符相比,function 关键字实际上不太可能返回正确的 this。如果您要在类中传递 function 关键字作为参数,那么您将使用的任何 this 都将退回到全局范围内。【参考方案2】:

私有属性只能在类声明本身内访问。您需要编写自己的序列化方法:

class Rectangle 
  #width;
  #height;
  constructor() 
    this.#width = 3;
    this.#height = 5;
  

  stringify() 
    return JSON.stringify(['#width']: this.#width,['#height']: this.#height)
  



let rect = new Rectangle();

console.log(rect.stringify())

【讨论】:

这就是我最终所做的,但使用了 toJSON 方法。我只是希望我不必写出每个给定班级中的每个成员,但如果是这种情况,那么我最终可能会完全放弃私有字段,这是一种耻辱。 私有字段的目的不就是它们是私有的吗?不允许序列化撤消吗? @evolutionxbox 在我的用例中使用 private 是为了防止这些特定成员在实例级别被篡改。对它们进行序列化不一定会破坏它。但我确实明白你的意思。

以上是关于Javascript 中的私有字段不会出现在 JSON.stringify 中的主要内容,如果未能解决你的问题,请参考以下文章

如何从 JavaScript 中的父类访问私有字段?

JS高级程序设计中对“私有作用域”的经典解释

装饰器和私有字段 javascript

如何对新的 JS 功能提出建议?

是否对独立 Swing 应用程序中的所有字段使用私有修饰符?

Javascript:如何将带有私有字段的对象保存到文件中?