不保证非数组对象的属性按任何特定顺序进行字符串化.不要依赖于字符串化内同一对象内的属性排序.
我曾希望通过缓存对象的字符串化版本来确定对象是否已更改,然后将其与随后的字符串化对象版本进行比较.这似乎比递归迭代对象并进行比较要简单得多.问题是因为JSON.stringify函数不是确定性的,所以当我对同一个对象进行字符串化时,我可以在技术上得到一个不同的字符串.
我还有其他选择吗?或者我是否必须编写令人讨厌的比较函数来确定对象相等性?
我很确定这是因为不同的JavaScript引擎在内部跟踪对象属性的方式.以此为例:
var obj = {
"1" : "test",
"0" : "test 2"
};
for(var key in obj) {
console.log(key);
}
Run Code Online (Sandbox Code Playgroud)
这将在例如Firefox中记录1,0,但在V8(Chrome和NodeJS)中记录0,1.因此,如果您需要确定性,您可能必须遍历数组中的每个密钥存储,对数组进行排序,然后通过循环遍历该数组来单独对每个属性进行字符串化.
你可能想尝试JSON.sortify,我写的一个小帮手.
与迄今为止给出的答案相反,它
space参数以及很少使用的replacer参数undefined价值和功能toJSON()下面是一个确定性的JSON.stringify(),我写的(使用的实现Underscore.js).它以递归方式将(非数组)对象转换为已排序的键值对(如数组),然后对这些对象进行字符串化.原始的coderwall发布在这里.
字符串化:
function stringify(obj) {
function flatten(obj) {
if (_.isObject(obj)) {
return _.sortBy(_.map(
_.pairs(obj),
function(p) { return [p[0], flatten(p[1])]; }
),
function(p) { return p[0]; }
);
}
return obj;
}
return JSON.stringify(flatten(obj));
}
Run Code Online (Sandbox Code Playgroud)
解析:
function parse(str) {
function inflate(obj, pairs) {
_.each(pairs, function(p) {
obj[p[0]] = _.isArray(p[1]) ?
inflate({}, p[1]) :
p[1];
});
return obj;
}
return inflate({}, JSON.parse(str));
}
Run Code Online (Sandbox Code Playgroud)