根据MDN documentation for JSON.stringify:
非数组对象的属性不能保证以任何特定的顺序进行字符串化。在字符串化中,不要依赖于同一对象内属性的排序。
我曾希望通过缓存对象的字符串化版本,然后将其与对象的后续字符串化版本进行比较来确定对象是否发生了变化。这似乎比递归迭代对象并进行比较要简单得多。问题是,由于JSON. stringify函数是不确定的,因此在技术上,当我字符串化同一对象时,可能会得到不同的字符串。
我还有什么其他的选择?或者我必须写一个讨厌的比较函数来确定对象是否相等?
9条答案
按热度按时间wlsrxk511#
我很确定这是因为不同的JavaScript引擎在内部跟踪对象属性的方式不同。
这将记录1,0在例如Firefox,但0,1在V8(Chrome和NodeJS).所以,如果你需要确定性,你可能要迭代通过每个关键字存储在一个数组,排序数组,然后字符串化每个属性分别通过循环通过该数组.
00jrzges2#
你可能想试试JSON.sortify,我写的一个小助手。
与迄今为止给出的答案相比,
space
参数以及很少使用的replacer
参数undefined
值和函数toJSON()
bf1o4zei3#
下面是我编写的一个确定性JSON.stringify()的实现(使用Underscore.js)。它递归地将(非数组)对象转换为排序的键值对(作为数组),然后将它们字符串化。
字符串化:
解析:
mec1mxoz4#
这些天来,我一直在尝试使用确定性方法来字符串化对象,我已经将有序对象字符串化写入JSON,这解决了上面提到的困境:http://stamat.wordpress.com/javascript-object-ordered-property-stringify/
此外,我还玩了自定义哈希表实现,这也是相关的主题:http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/
ndasle7k5#
使用下划线或虚线:
适用于最新的Chrome和Firefox浏览器。
JSFiddle在这里:http://jsfiddle.net/stchangg/ruC22/2/
relj7zay6#
最近我有一个类似的用例,下面的代码没有依赖关系,适用于所有浏览器:
stringify([{b: {z: 5, c: 2, a: {z: 1, b: 2}}, a: 1}, [1, 2, 3]])
'[{"a":1,"b":{"a":{"b":2,"z":1},"c":2,"z":5}},[1,2,3]]'
stringify([{a: 1, b:{z: 5, c: 2, a: {b: 2, z: 1}}}, [1, 2, 3]])
'[{"a":1,"b":{"a":{"b":2,"z":1},"c":2,"z":5}},[1,2,3]]'
vhipe2zx7#
JavaScript键本质上是无序的。你必须写你自己的字符串才能使这个工作,所以我做了。
用法:
资料来源:
cuxqih218#
您可能需要考虑的一些事项:对象不同意味着什么?您是否希望查看该对象上的属性是否已更改?谁对“了解”这些更改感兴趣?您是否希望立即了解对象属性是否已更改?
你可以让对象的属性成为“可观察的”属性,当属性改变时,你可以触发一个事件,任何感兴趣的人都可以订阅这些属性的改变。这样你就可以立即知道什么改变了,你可以对这些信息做任何你想做的事情。Knockout.js使用这种方法。这样你就不必求助于“讨厌的”对象比较
ghhaqwfi9#
已接受的答案不再正确。
所有浏览器现在都以相同的顺序对键进行排序:
{ 1: "anything" }
{ 01: "anything" }
将生成数值字段1
{ "01": "anything" }
将生成字符串字段"01"
在执行
JSON.stringify
、Object.getOwnPropertyNames
和for (var key in obj)
时应用相同的排序。确认日期:Safari浏览器、Chrome浏览器、火狐浏览器、Edge浏览器、IE11。
这意味着您可以使用
JSON.stringify
检查对象是否被修改。只有一个条件:你不能使用
delete
操作来删除字符串字段,因为如果它们被再次添加,它们将被添加到字段列表的末尾。您还可以使用
JSON.stringify
来比较两个不同的对象,只要您知道它们的字段是以相同的顺序创建的。我必须补充的是,即使所有的JS引擎目前都以相同的方式处理对象,也不能保证将来会是这样,所以最好还是使用一个特殊的工具来进行比较。
我建议使用带有
strict: true
选项的deep-equal模块。