为什么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规格 :
如果PropertyList不是未定义的,那么
一个。 设K为PropertyList。
其他
一个。 设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!" }