JSON.parse Reviver 函数中的异常行为,删除对象而不是关键属性

Unexpected behavior in JSON.parse Reviver function, deleting the object and not the key properties

JSBin link 以便您可以 运行 快速编写代码。

JSbinhere

问题出在评论中,但从文档中可以看出 reviver(那个名字很糟糕)的工作原理,如果你没有 return 一个值或者你 return undefined 那么 属性 应该从对象中删除。如果您 return 未转换的值,它将保持不变。

然而,当我对其进行测试时,看起来整个对象都被删除了。第一个例子工作得很好,偶数被转换为负数,奇数不变。

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

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

    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

你的第二个例子 return value; 关闭。

但即使你那样做了,它也应该只删除了 returned undefined 作为值的属性,我认为你发现了一个错误(可能是?)。

MDN JSON.parse examples 之一说当调用 JSON.parse 时最后一个键是 ""

我成功地重现了你的代码,但出现了 undefined 错误,看来如果你 return "" 键的值,比如

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函数的行为f时,调用所有DefineOwnProperty项后的最后一步是

Return the result of calling the abstract operation Walk, passing root and the empty String.

所以,当你在你的 reviver 函数中没有 return '' 名称的值时,它明白它应该删除它,它代表整个对象是 returned,导致 JSON.parse return.

undefined

这解释了 MDN 文档中提到的问题

be certain to return all untransformed values as-is

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