为什么JSON.stringify不序列化原型值?

我一直在处理一些JSONparsing,并最近在Node.js和浏览器中传入Javascript,并碰到了这个难题。

我使用构造函数创build的任何对象都不能完全通过JSON.stringify完全序列化,除非我单独初始化构造函数中的所有值! 这意味着我的原型在devise这些类时变得基本没用。

有人可以解释为什么以下不按我所期望的序列化?

var ClassA = function () { this.initialisedValue = "You can see me!" }; ClassA.prototype = { initialisedValue : "You can't see me!", uninitialisedValue : "You can't see me!" }; var a = new ClassA(); var a_string = JSON.stringify(a); 

怎么了:

a_string == {“initialisedValue”:“你可以看到我!” }

我会期待:

a_string == {“initialisedValue”:“你可以看到我!”,“uninitialisedValue”:“你看不到我!” }

只是因为这是JSON的工作方式。 从ES5规格 :

设K是由[[Enumerable]]属性为true的所有属性值的名称组成的内部string列表。

这是有道理的,因为JSON规范中没有任何机制保留将JSONstringparsing回JavaScript对象(如果包含inheritance属性)所需的信息。 在你的例子中,这将如何parsing:

{“initialisedValue”:“你可以看到我!”,“uninitialisedValue”:“你看不到我!” }

除了具有2个键值对的扁平物体以外,没有任何信息可以parsing为任何信息。

如果你考虑一下,JSON并不是直接映射到JavaScript对象的。 其他语言必须能够将JSONstringparsing为名称 – 值对的简单结构。 如果JSONstring包含了序列化完整JavaScript范围链所需的所有信息,其他语言可能不太能够将其parsing为有用的东西。 用json.org上的Douglas Crockford的话来说 :

这些[哈希表和数组]是通用的数据结构。 几乎所有的现代编程语言都以不同的forms支持它们。 有意义的是,与编程语言可互换的数据格式也基于这些结构。

我使用mongoose登陆这个页面:如果其他用户有类似的问题,下面的问题(和相关的答案)可能是有用的:

你如何将一个Mongoose文档变成一个普通的对象?

(基本上:使用模型的toObject()方法)

我想补充一点,即使JSON.stringify只会对对象自己的属性进行string化,正如接受的答案中所解释的那样,通过指定一个String数组作为JSON.stringify的第二个参数,可以改变string化过程的行为JSON.stringify (称为替代者数组)。

如果您指定一个String数组和String的属性白名单,string化algorithm将改变其行为,它会考虑原型链中的属性。

从ES5规格 :

  1. 如果PropertyList不是未定义的,那么

    一个。 设K为PropertyList。

  2. 其他

    一个。 设K是由[[Enumerable]]属性为true的所有属性值的名称组成的内部string列表。 string的排列顺序应与Object.keys标准内置函数所使用的顺序相同。

如果您事先知道对象的属性的名称,则可以这样做:

 var a_string = JSON.stringify(a, ["initialisedValue", "uninitialisedValue"]); // a_string == { "initialisedValue" : "You can see me!", "uninitialisedValue" : "You can't see me!" }