带有replacer函数的JSON.stringify中的奇怪行为

Pat*_*mek 9 javascript json

考虑一下:

var object = {date: new Date()};

JSON.stringify(object, function(key, value) {
    console.log('---');
    console.log('key:', key);
    console.log('value:', value);
    console.log('value instanceof Date:', value instanceof Date);

    return value;
});
Run Code Online (Sandbox Code Playgroud)

正如文件所说:

replacer参数可以是函数或数组.作为一个函数,它需要两个参数,键和值被字符串化.找到密钥的对象作为replacer的this参数提供.最初使用表示要进行字符串化的对象的空键调用它,然后为要进行字符串化的对象或数组上的每个属性调用它.

...

如果返回任何其他对象,则会以递归方式将对象字符串化为JSON字符串,并在每个属性上调用replacer函数,除非该对象是函数,在这种情况下,不会向JSON字符串添加任何内容.

但是如果你运行代码,你会得到这个:

---
key: 
value: { date: Fri Jan 10 2014 02:25:00 GMT+0100 (CET) }
value instanceof Date: false
---
key: date
value: 2014-01-10T01:25:00.262Z
value instanceof Date: false
Run Code Online (Sandbox Code Playgroud)

这意味着,在调用replacer函数之前,date属性已被字符串化.这是正常的行为还是我错过了什么?如何在Date不覆盖默认toJSON方法的情况下影响字符串化的格式?

谢谢!

编辑

根据回答和下一步的研究,文献似乎目前还不清楚,toJSON并且在更换器功能之前就已经被调用了.根据Pills的回复,这个片段应该可以完成这项任务:

var object = {date: new Date };

JSON.stringify(object, function(key, value) {
    if (typeof(value) === 'object') {
        for (var k in value) {
            if (value[k] instanceof Date) {
                value[k] = value[k].getTime();
            }
        }
    }
    return value;
});
Run Code Online (Sandbox Code Playgroud)

编辑#2

Xotic750的解决方案比以前的解决方案要好得多.

Fis*_*Fis 8

它安静的旧但只是为了完成它。

根据这个 Q/AMDN JSON.stringify 文章替换器是用找到键的对象的实例调用的,所以不需要更改原型或做其他技巧:

function log(what) {
   what = what || "";
   document.getElementById("out").innerText += what + "\n";
}

function replacer(key, value) {
   console.log(this);
   log("Key: '" + key + "' = '" + value + "'");
   log("this = " + this);
   log("this[key] = " + this[key]);
   log("this[key] instanceof Date = " + (this[key] instanceof Date));
   log("this instanceof Date = " + (this[key] instanceof Date));
   
   if (this[key] instanceof Date) {
      return "This was a date: " + this[key].getTime();
   }
   
   return value;
}

var obj = {
   d: new Date()
};

var result;
result = JSON.stringify(new Date(), replacer);
log();
log(result);
log();
result = JSON.stringify(obj, replacer);
log();
log(result);
Run Code Online (Sandbox Code Playgroud)
<pre id="out"></pre>
Run Code Online (Sandbox Code Playgroud)


Xot*_*750 4

也许您可以在将对象传递给 之前进行格式化JSON,但否则这里有一种可能性:

JSONtoJSON在调用替换器之前使用对象方法。

因此,在调用之前stringify存储该toJSON方法,然后再恢复它。

var object = {
        date: new Date()
    },
    storeToJSON = Date.prototype.toJSON;

delete Date.prototype.toJSON;

JSON.stringify(object, function (key, value) {
    console.log('---');
    console.log('key:', key);
    console.log('value:', value);
    console.log('value instanceof Date:', value instanceof Date);

    return value;
});

Date.prototype.toJSON = storeToJSON;
Run Code Online (Sandbox Code Playgroud)

关于jsFiddle