JSON object != JavaScript object? [duplicate]
Asked Answered
M

3

6

For convenience I wrote a simple toJSON prototype, for handling JSON that I know to be safe:

String.prototype.toJSON = function () {
    return JSON.parse(this.valueOf());
};

I am using it in testing my web-services. Unfortunately even with this simple test:

var v0 = '{"echo":"hello_world"}'.toJSON(), v1 = {"echo": "hello_world"};

It fails:

console.log(v0 == v1);            // false
console.log(v0 === v1);           // false
console.log(v0.echo == v1.echo);  // true
console.log(v0.echo === v1.echo); // true

What do I not know about JavaScript which is causing this issue?

Mecklenburg answered 22/12, 2013 at 11:39 Comment(4)
"toJSON" is actually doing "fromJSON".Housefather
see: #201683Sassy
Possible duplication: #1069334Callipash
{a:1} !== {a:1}. Two objects are the same... if they are the same one, and point to the same object in the heap.Bilabial
I
2

An object in JavaScript, just like everything else except primitives(int, string, Boolean) is a reference.

Having 2 different duplicate objects, means having 2 different references that point to different places within the hype.

You can implement something as simple as that, to basically iterate over all of the primitive properties of an object, and compare them one by one:

Object.prototype.equals = function(x)
{
    for(p in this)
    {
        switch(typeof(this[p]))
        {
            case 'object':
                if (!this[p].equals(x[p])) { return false }; break;
            case 'function':
                if (typeof(x[p])=='undefined' || (p != 'equals' && this[p].toString() != x[p].toString())) { return false; }; break;
            default:
                if (this[p] != x[p]) { return false; }
        }
    }

    for(p in x)
    {
        if(typeof(this[p])=='undefined') {return false;}
    }

    return true;
}
Indihar answered 22/12, 2013 at 11:46 Comment(2)
Thanks, this looks rather simple. Is the stack-based underscore one higher performance?Mecklenburg
Both of the methods conduct a recursive compression, generally speaking the time complexity is log(n) in both cases.Indihar
S
3

Just because you have the same content, that does not mean that you have the same object instance. If you had done v1 = v0 instead of initializing v1 seperatly the first two would have returned true.

Update: If you need to compare the two instances to find if they have equal content then you need to define a function which compares each member.

Sur answered 22/12, 2013 at 11:42 Comment(1)
I am getting v0 from an HTTP GET request; and have a test which ensures that what I get from the HTTP GET matches my expectation.Mecklenburg
I
2

An object in JavaScript, just like everything else except primitives(int, string, Boolean) is a reference.

Having 2 different duplicate objects, means having 2 different references that point to different places within the hype.

You can implement something as simple as that, to basically iterate over all of the primitive properties of an object, and compare them one by one:

Object.prototype.equals = function(x)
{
    for(p in this)
    {
        switch(typeof(this[p]))
        {
            case 'object':
                if (!this[p].equals(x[p])) { return false }; break;
            case 'function':
                if (typeof(x[p])=='undefined' || (p != 'equals' && this[p].toString() != x[p].toString())) { return false; }; break;
            default:
                if (this[p] != x[p]) { return false; }
        }
    }

    for(p in x)
    {
        if(typeof(this[p])=='undefined') {return false;}
    }

    return true;
}
Indihar answered 22/12, 2013 at 11:46 Comment(2)
Thanks, this looks rather simple. Is the stack-based underscore one higher performance?Mecklenburg
Both of the methods conduct a recursive compression, generally speaking the time complexity is log(n) in both cases.Indihar
D
1

For two objects to be == they must be the same instance. v0 and v1 are two different instances. If you want to do a deep comparison of objects you can use something like underscore's isEqual method: http://underscorejs.org/#isEqual

_.isEqual(v0, v1);
Debunk answered 22/12, 2013 at 11:44 Comment(4)
Oh okay, didn't know that a deep comparison operator wasn't supported out-of-the-box in JavaScript. Will consider using, e.g. this.Mecklenburg
It is not about deep comparison. Two objects are equal if they are the same object. One thing is comparing the object, and another one is to compare the value (which is what _.isEqual does).Bilabial
Thanks, I was easily able to get underscore to work within my scope.Mecklenburg
From underscores API docs on isEqual: Performs an optimized deep comparison between the two objects, to determine if they should be considered equal.Debunk

© 2022 - 2024 — McMap. All rights reserved.