3

I have the following code:

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

I JSON.parse a JSON.stringify object (that contained a function), but the result was undefined. Why is this?

Joe C.
  • 397
  • 4
  • 15
  • 1
    The condition will return `false` even if you strip out the `JSON.stringify` and `JSON.parse`. See https://stackoverflow.com/a/9817706/4636715 for comparing functions. – vahdet Jul 03 '18 at 06:29
  • 1
    Two individual objects are never equal to each other: `console.log({} === {})` – Felix Kling Jul 03 '18 at 06:31

4 Answers4

3

See this question.

JSON.stringify() will encode values that JSON supports. Objects with values that can be objects, arrays, strings, numbers and booleans. Anything else will be ignored or throw errors. Functions are not a supported entity in JSON. JSON handles pure data only, functions are not data, but behavior with more complex semantics.

This means that using JSON.parse(JSON.stringify()) on a object with methods will not be equal to the object that hasn't been stringified.

Kairowa
  • 1,111
  • 1
  • 10
  • 16
3

JSON.stringify() will encode values that JSON supports. Objects with values that can be objects, arrays, strings, numbers and booleans. Anything else will be ignored or throw errors. Functions are not a supported entity in JSON. JSON handles pure data only, functions are not data, but behaviour with more complex semantics.

So, basically you need your own reducer and parsers while stringifying and parsing object and that can be done as:

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));
Namit Jain
  • 31
  • 1
1

Because Object is a reference type, JSON.parse(JSON.stringify()) returns a new Object, and the == expression compares their address when comparing reference types, so it returns false.

xujizhong
  • 42
  • 3
0

I think the answer to your question can be demonstrated as:

console.log({} == {});

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

In the first case, we are comparing 2 new empty Objects. Each Object has its own allocation in memory, and so when comparing reference types, this is what is compared. Therefore, false is returned as they are not the same.

In the second example, we "point" a new variable (test) to an existing Object (example). Here we see that it returns true because this time we are comparing the same memory allocation.

Zze
  • 18,229
  • 13
  • 85
  • 118