【问题标题】:JSON.parse(JSON.stringify(object_with_function)) != object_with_functionJSON.parse(JSON.stringify(object_with_function)) != object_with_function
【发布时间】:2018-07-03 06:05:30
【问题描述】:

所以我有以下代码:

alert(JSON.parse(JSON.stringify({func: function(){alert(1);}})) == {func: function(){alert(1);}});

基本上,我 JSON.parse 一个 JSON.stringify 对象(包含一个函数),结果与原始对象不同(警报时我得到了错误)

这让我陷入了游戏的保存进度功能。

帮助表示赞赏!

编辑: 对不起,不好的例子,试试这个:

alert(JSON.parse(JSON.stringify({func: function(){alert(1);}})).func);

它提醒未定义。

【问题讨论】:

  • 只是为了澄清,我的警报是错误的。如果你们是真的,那可能是我的电脑坏了
  • 即使去掉JSON.stringify 和JSON.parse,条件也会返回false。函数比较见stackoverflow.com/a/9817706/4636715。
  • 两个单独的对象永远不会相等:console.log({} === {})
  • 好的,所以我有一个误导性的例子,看看这段代码:alert(JSON.parse(JSON.stringify({func: function(){alert(1);}})).func);

标签: javascript


【解决方案1】:

见this question。

JSON.stringify() 将对 JSON 支持的值进行编码。对象与 可以是对象、数组、字符串、数字和布尔值的值。 其他任何内容都将被忽略或抛出错误。函数不是一个 JSON 中支持的实体。 JSON 只处理纯数据,函数是 不是数据,而是具有更复杂语义的行为。

这意味着在带有方法的对象上使用 JSON.parse(JSON.stringify()) 将不等于未字符串化的对象。

【讨论】:

  • 我想这就是我需要的。对不起,我有一个非常糟糕和误导性的例子。看看这个例子: alert(JSON.parse(JSON.stringify({func: function(){alert(1);}})).func);
【解决方案2】:

因为Object是引用类型,所以JSON.parse(JSON.stringify())返回一个新的Object,而==表达式在比较引用类型的时候会比较它们的地址,所以返回false。

【讨论】:

  • 我认为您的意思是“对象”而不是“功能”。
  • 你不会得到不同的功能。您根本无法从 JSON 中获取函数对象,因为 JSON 不支持函数。
【解决方案3】:

JSON.stringify() 将对 JSON 支持的值进行编码。对象与 可以是对象、数组、字符串、数字和布尔值。 其他任何内容都将被忽略或抛出错误。函数不是一个 JSON 中支持的实体。 JSON 只处理纯数据,函数是 不是数据,而是具有更复杂语义的行为。

所以,基本上你在对对象进行字符串化和解析时需要自己的 reducer 和解析器,可以这样做:

var myObject = {
        num: 50,
        str: 'A string here',
        today: new Date(),
        ar: ['one', 'two', 'three'],
        myFunction: function(val) {
            console.log(val);
        }
    }

    // example replacer function
    function replacer(name, val) {
        // convert RegExp or function to string
        if ( val && val.constructor === Function) {
            return val.toString();
        } else {
            return val; // return as is
        }
    };

    // example replacer function
    function parser(name, val) {
        if ( val && typeof val == "string" && val.startsWith("function")){
            return new Function('return ' + val)();
        } else {
            return val; // return as is
        }
    };
    var jsonObject = JSON.parse(JSON.stringify(myObject, replacer), parser);

    //because of different reference , this will evaluate to false
    console.log(myObject.myFunction == jsonObject.myFunction);
    //true because of same content
    console.log(myObject.myFunction.toString() == jsonObject.myFunction.toString());
    //evaluate same as same function
    console.log(myObject.myFunction(5) == jsonObject.myFunction(5));

【讨论】:

    【解决方案4】:

    我认为你的问题的答案可以证明为:

    console.log({} == {});
    
    var example = {};
    var test = example;
    console.log(example == test);

    在第一种情况下,我们正在比较 2 个新的空对象。每个对象在内存中都有自己的分配,因此在比较引用类型时,这就是比较的内容。因此,false 被返回,因为它们不一样。

    在第二个示例中,我们将一个新变量 (test) “指向”一个现有对象 (example)。在这里我们看到它返回true,因为这次我们比较的是相同的内存分配。

    【讨论】:

    • 看看这个我有一个误导性的例子 alert(JSON.parse(JSON.stringify({func: function(){alert(1);}})).func);
    • @JasonC。函数不能被字符串化。
    猜你喜欢
    • 2014-07-06
    • 2018-03-10
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 2015-01-25
    • 2022-01-25
    • 2014-09-11
    相关资源
    最近更新 更多