【问题标题】:Javascript JSON.stringify doesn't handle prototype correctly?Javascript JSON.stringify 不能正确处理原型?
【发布时间】:2014-02-12 15:32:56
【问题描述】:

我一直在像这样初始化我的可重用类(构造函数通常是复制构造函数):

function Foo() {}
Foo.prototype.a = "1";
Foo.prototype.b = "2";
Foo.prototype.c = [];
var obj = new Foo();
obj.c.push("3");

但是 JSON.stringify 没有产生预期的结果:

JSON.stringify(obj);

{}

变量在其他所有方面都按预期工作。
如果 toJSON 被覆盖,它工作正常:

Foo.prototype.toJSON = function () {
    return {
        a: this.a,
        b: this.b,
        c: this.c
    };
};
JSON.stringify(obj);

{"a":"1","b":"2","c":["3"]}

如果在构造函数中定义变量也可以正常工作:

function Alt() {
    this.a = 1;
    this.b = "2";
    this.c = [];
}
JSON.stringify(obj);

{"a":1,"b":"2","c":["3"]}

发生了什么事?

这里的例子: http://jsfiddle.net/FdzB6/

【问题讨论】:

  • JSON 序列化器只关注被序列化对象上的属性(“自己的”属性)。
  • @MikeEmery 代表“Foo”,函数?!?不,函数 "Foo" 没有这些属性,通过调用 new Foo 创建的对象也不会 - 当然,它们将通过实例从原型中可读,但是hasOwnProperty("a") 测试将返回 false
  • @RocketHazmat 是的;简单的字符串或数值原型属性与函数属性之间实际上没有区别。属性引用的查找过程是相同的。我想我应该添加一个答案:)
  • 作为参考,这里是 Crockford 的 stringify 的实现方式:github.com/douglascrockford/JSON-js/blob/master/json2.js#L326
  • @MikeEmery 好吧,这取决于您要做什么。如果使用 JSON 序列化对象的能力真的很重要,那么是的,我会说这是个坏主意 :)

标签: javascript json prototype


【解决方案1】:

对象原型(即其构造函数的原型)上的属性通过对对象的引用可读

function Constructor() { }
Constructor.prototype.a = "hello world";

var x = new Constructor();
alert(x.a); // "hello world"

但是,这些属性确实“卡在”原型对象上:

alert(x.hasOwnProperty("a")); // false

JSON 序列化程序只关注直接出现在正在处理的对象上的属性。这有点痛苦,但如果您考虑一下相反的过程,这有点道理:您当然不希望 JSON.parse() 将属性放回原型上(无论如何这将非常棘手)。

【讨论】:

  • 感谢您的解释 - 关于稍后使用 JSON.parse 的一点特别有用。
【解决方案2】:

你的答案在于Why is JSON.stringify not serializing prototype values?

JSON.stringify 只做“自己的”属性。

在您的第一个示例中: 正在设置原型成员,然后在对象本身上调用Stringify,它没有自己的属性。

第二次: this.a 会爬上链条直到找到属性

在第三个: 您是直接在对象上设置属性,而不是在其原型上

【讨论】:

    猜你喜欢
    • 2012-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多