JSON.parse Reviver函数中出现意外行为,删除对象而不是键属性

时间:2016-10-23 20:36:56

标签: javascript json reviver-function

JSBin链接,以便您可以快速运行代码。

JSbinhere

问题出现在评论中,但是从文档中说明了reviver(该名称是如何可怕的)如何工作,如果你没有返回一个值或者你返回undefined那么该属性应该是从对象中删除。如果返回未转换的值,则保持不变。

然而,当我测试它时,看起来整个对象都被移除了。第一个例子工作正常,偶数转换为负数,奇数不变。

但在第二个例子中,我甚至没有得到一个对象,只是未定义。我是误读文档还是其他错误?

结果在第二个例子中未定义。

    var obj = {
            one: 1,
            innerObj: {
                two: 2,
                four: 4
            },
            two: 2,
            three: 3,
            four: 4
        },
            b = {},
            json = JSON.stringify(obj);
        /**
         *  This works as expected.
         */
        b = JSON.parse(json, function (name, value) {
            if (value % 2 === 0) {
                return -value;
            }
            return value;
        });
        console.log(b);
    /**
    [object Object] {
   four: -4,
   innerObj: [object Object] {
    four: -4,
    two: -2
   },
   one: 1,
   three: 3,
   two: -2
    } 
    */

    obj = {
            one: 1,
            innerObj: {
                two: 2,
                four: 4
            },
            two: 2,
            three: 3,
            four: 4
        };
        b = {};
        json = JSON.stringify(obj);
        /**
         * This does not work as expected, instead of deleting the property on the object, the entire object returns undefined.
         */
        b = JSON.parse(json, function (name, value) {
            if (value % 2 === 0) {
                return -value;
            }

        });
        console.log(b);
// undefined

1 个答案:

答案 0 :(得分:1)

您的第二个示例已关闭return value;

但即使你做到了这一点,它应该只删除返回undefined作为值的属性,我认为你发现了一个错误(可能是?)。

来自MDN JSON.parse examples之一,当调用""时,它表示最后一个密钥为JSON.parse

我设法使用undefined错误重现您的代码,似乎如果您返回""键的值,例如

if (name == "") {
  return value;
}

它似乎按预期工作。

obj = {
   one: 1,
   innerObj: {
     two: 2,
     four: 4
   },
   two: 2,
   three: 3,
   four: 4
};
b = {};
json = JSON.stringify(obj);


/**
* This does not work as expected, instead of deleting the property on the object, the entire object returns undefined.
*/
b = JSON.parse(json, function (name, value) {
  if (value % 2 === 0) {
    return -value;
  }
  if (name == "") {
    return value;
  }
});
console.log(b);
// { two: -2, four: -4 }

编辑:

所以,阅读ECAMScript JSON.parse(text [, reviver]) specification,似乎这是预期的行为。当它描述调用reviver函数的行为时,调用所有DefineOwnProperty项后的最后一步是

  

返回调用抽象操作Walk的结果,传递root和空字符串。

所以,当你没有在你的reviver函数中返回''名称的值时,它会理解它应该删除它,它代表要返回的整个对象,导致它为{{ 1}}用于undefined返回。

这解释了MDN文档的关注点

  

确保按原样返回所有未转换的值

但我同意应该更明确地说明这些小细微差别是如何运作的。