Obiect JSON != Obiect JavaScript?


Pentru comoditate, am scris un prototip simplu toJSON, pentru a gestiona JSON-ul despre care știu că este sigur:

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

Îl folosesc pentru a testa serviciile mele web. Din păcate, chiar și cu acest test simplu:

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

Eșuează:

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

Ce nu știu despre JavaScript care cauzează această problemă?

Răspuns #1

Doar pentru că aveți același conținut, asta nu înseamnă că aveți aceeași instanță de obiect. Dacă ați fi făcut v1=v0 în loc să inițializați v1 separat, primele două ar fi returnat adevărat.

Actualizare: Dacă trebuie să compari cele două instanțe pentru a afla dacă au conținut egal, atunci trebuie să definești o funcție care compară fiecare membru.

Răspunsul #2

Un obiect în JavaScript, la fel ca toate celelalte în afară de primitive (int, string, Boolean), este o referință.

A avea 2 obiecte duplicate diferite înseamnă a avea 2 referințe diferite care indică spre locuri diferite în cadrul hype-ului.

Poți implementa ceva la fel de simplu, practic să iterezi peste toate proprietățile primitive ale unui obiect și să le compari pe rând:

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;
}