995 Stimmen

Wie bestimmt man die Gleichheit zweier JavaScript-Objekte?

Ein strikter Gleichheitsoperator sagt Ihnen, ob zwei Objekte Typen gleich sind. Gibt es jedoch eine Möglichkeit zu erkennen, ob zwei Objekte gleich sind, ähnlich wie der Hash-Code Wert in Java?

Stack Overflow Frage Gibt es irgendeine Art von HashCode-Funktion in JavaScript? ist dieser Frage ähnlich, erfordert aber eine eher akademische Antwort. Das obige Szenario zeigt, warum es notwendig wäre, eine zu haben, und ich frage mich, ob es irgendeine gleichwertige Lösung .

5 Stimmen

Gehen Sie auch dieser Frage nach stackoverflow.com/q/1068834/1671639

55 Stimmen

Beachten Sie, dass auch in Java, a.hashCode() == b.hashCode() tut no bedeuten, dass a ist gleich b . Das ist eine notwendige, aber keine hinreichende Bedingung.

7 Stimmen

Wenn Sie Objekte in Ihrem Code vergleichen MÜSSEN, dann haben Sie Ihren Code wahrscheinlich falsch geschrieben. Die bessere Frage könnte lauten: "Wie kann ich diesen Code so schreiben, dass ich keine Objekte vergleichen muss?"

-1voto

Sandeep Punkte 26349

Überprüfung der Objektgleichheit: JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

Der obige Test funktioniert auch mit Arrays von Objekten. In diesem Fall verwenden Sie eine Sortierfunktion, wie sie in http://www.w3schools.com/jsref/jsref_sort.asp

Könnte für kleine Arrays mit flachen JSON-Schemata ausreichen.

3 Stimmen

Funktioniert nicht garantiert - Objekteigenschaften sind ungeordnet [bestimmte Reihenfolge nie garantiert] gemäß der EcmaScript 3-Spezifikation .

0 Stimmen

Viele Probleme siehe stackoverflow.com/a/201305/3780629

-1voto

Kevin Teljeur Punkte 2093

Klar, wenn wir schon dabei sind, werde ich das Rad selbst neu erfinden (ich bin stolz auf die Anzahl der Speichen und die verwendeten Materialien):

////////////////////////////////////////////////////////////////////////////////

var equals = function ( objectA, objectB ) {
    var result = false,
        keysA,
        keysB;

    // Check if they are pointing at the same variable. If they are, no need to test further.
    if ( objectA === objectB ) {
        return true;
    }

    // Check if they are the same type. If they are not, no need to test further.
    if ( typeof objectA !== typeof objectB ) {
        return false;
    }

    // Check what kind of variables they are to see what sort of comparison we should make.
    if ( typeof objectA === "object" ) {
        // Check if they have the same constructor, so that we are comparing apples with apples.
        if ( objectA.constructor === objectA.constructor ) {
            // If we are working with Arrays...
            if ( objectA instanceof Array ) {
                // Check the arrays are the same length. If not, they cannot be the same.
                if ( objectA.length === objectB.length ) {
                    // Compare each element. They must be identical. If not, the comparison stops immediately and returns false.
                    return objectA.every(
                        function ( element, i ) {
                            return equals( element, objectB[ i ] );
                        }
                    );
                }
                // They are not the same length, and so are not identical.
                else {
                    return false;
                }
            }
            // If we are working with RegExps...
            else if ( objectA instanceof RegExp ) {
                // Return the results of a string comparison of the expression.
                return ( objectA.toString() === objectB.toString() );
            }
            // Else we are working with other types of objects...
            else {
                // Get the keys as arrays from both objects. This uses Object.keys, so no old browsers here.
                keysA = Object.keys( objectA );

                keysB = Object.keys( objectB );

                // Check the key arrays are the same length. If not, they cannot be the same.
                if ( keysA.length === keysB.length ) {
                    // Compare each property. They must be identical. If not, the comparison stops immediately and returns false.
                    return keysA.every(
                        function ( element ) {
                            return equals( objectA[ element ], objectB[ element ] );
                        }
                    );
                }
                // They do not have the same number of keys, and so are not identical.
                else {
                    return false;
                }
            }
        }
        // They don't have the same constructor.
        else {
            return false;
        }
    }
    // If they are both functions, let us do a string comparison.
    else if ( typeof objectA === "function" ) {
        return ( objectA.toString() === objectB.toString() );
    }
    // If a simple variable type, compare directly without coercion.
    else {
        return ( objectA === objectB );
    }

    // Return a default if nothing has already been returned.
    return result;
};

////////////////////////////////////////////////////////////////////////////////

Es gibt so schnell wie möglich false zurück, aber bei einem großen Objekt, bei dem der Unterschied tief verschachtelt ist, könnte es natürlich weniger effektiv sein. In meinem eigenen Szenario ist eine gute Handhabung von verschachtelten Arrays wichtig.

Ich hoffe, es hilft jemandem, der diese Art von "Rad" braucht.

-1voto

Tommaso Bertoni Punkte 2156

Ja, noch eine Antwort...

Object.prototype.equals = function (object) {
    if (this.constructor !== object.constructor) return false;
    if (Object.keys(this).length !== Object.keys(object).length) return false;
    var obk;
    for (obk in object) {
        if (this[obk] !== object[obk])
            return false;
    }
    return true;
}

var aaa = JSON.parse('{"name":"mike","tel":"1324356584"}');
var bbb = JSON.parse('{"tel":"1324356584","name":"mike"}');
var ccc = JSON.parse('{"name":"mike","tel":"584"}');
var ddd = JSON.parse('{"name":"mike","tel":"1324356584", "work":"nope"}');

$("#ab").text(aaa.equals(bbb));
$("#ba").text(bbb.equals(aaa));
$("#bc").text(bbb.equals(ccc));
$("#ad").text(aaa.equals(ddd));

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
aaa equals bbb? <span id="ab"></span> <br/>
bbb equals aaa? <span id="ba"></span> <br/>
bbb equals ccc? <span id="bc"></span> <br/>
aaa equals ddd? <span id="ad"></span>

0 Stimmen

Behandelt keine verschachtelten Objekte

-1voto

Apaar Bhatnagar Punkte 109

Obwohl es bereits so viele Antworten auf diese Frage gibt. Ich versuche nur, eine weitere Möglichkeit der Umsetzung zu bieten:

const primitveDataTypes = ['number', 'boolean', 'string', 'undefined'];
const isDateOrRegExp = (value) => value instanceof Date || value instanceof RegExp;
const compare = (first, second) => {
    let agg = true;
    if(typeof first === typeof second && primitveDataTypes.indexOf(typeof first) !== -1 && first !== second){
        agg =  false;
    }
    // adding support for Date and RegExp.
    else if(isDateOrRegExp(first) || isDateOrRegExp(second)){
        if(first.toString() !== second.toString()){
            agg = false;
        }
    }
    else {
        if(Array.isArray(first) && Array.isArray(second)){
        if(first.length === second.length){
             for(let i = 0; i < first.length; i++){
                if(typeof first[i] === 'object' && typeof second[i] === 'object'){
                    agg = compare(first[i], second[i]);
                }
                else if(first[i] !== second[i]){
                    agg = false;
                }
            }
        } else {
            agg = false;
        }
    } else {
        const firstKeys = Object.keys(first);
        const secondKeys = Object.keys(second);
        if(firstKeys.length !== secondKeys.length){
            agg = false;
        }
        for(let j = 0 ; j < firstKeys.length; j++){
            if(firstKeys[j] !== secondKeys[j]){
                agg = false;
            }
            if(first[firstKeys[j]] && second[secondKeys[j]] && typeof first[firstKeys[j]] === 'object' && typeof second[secondKeys[j]] === 'object'){
                agg = compare(first[firstKeys[j]], second[secondKeys[j]]);
             } 
             else if(first[firstKeys[j]] !== second[secondKeys[j]]){
                agg = false;
             } 
        }
    }
    }
    return agg;
}

console.log('result', compare({a: 1, b: { c: [4, {d:5}, {e:6}]}, r: null}, {a: 1, b: { c: [4, {d:5}, {e:6}]}, r: 'ffd'}));  //returns false.

-1voto

pmrotule Punkte 7745

Ich habe eine viel kürzere Funktion, die tief in alle Unterobjekte oder Arrays eindringen kann. Sie ist genauso effizient wie JSON.stringify(obj1) === JSON.stringify(obj2) sondern JSON.stringify wird nicht funktionieren, wenn die Reihenfolge nicht die gleiche ist ( wie hier erwähnt ).

var obj1 = { a : 1, b : 2 };
var obj2 = { b : 2, a : 1 };

console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // false

Die Funktion wäre auch ein guter Anfang, wenn Sie etwas mit den ungleichen Werten machen wollen.

function arr_or_obj(v)
{ return !!v && (v.constructor === Object || v.constructor === Array); }

function deep_equal(v1, v2)
{
    if (arr_or_obj(v1) && arr_or_obj(v2) && v1.constructor === v2.constructor)
    {
        if (Object.keys(v1).length === Object.keys(v2).length) // check the length
        for (var i in v1)
        {
            if (!deep_equal(v1[i], v2[i]))
            { return false; }
        }
        else
        { return false; }
    }
    else if (v1 !== v2)
    { return false; }

    return true;
}

//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

var obj1 = [
    {
        hat : {
            cap : ['something', null ],
            helmet : [ 'triple eight', 'pro-tec' ]
        },
        shoes : [ 'loafer', 'penny' ]
    },
    {
        beers : [ 'budweiser', 'busch' ],
        wines : [ 'barefoot', 'yellow tail' ]
    }
];

var obj2 = [
    {
        shoes : [ 'loafer', 'penny' ], // same even if the order is different
        hat : {
            cap : ['something', null ],
            helmet : [ 'triple eight', 'pro-tec' ]
        }
    },
    {
        beers : [ 'budweiser', 'busch' ],
        wines : [ 'barefoot', 'yellow tail' ]
    }
];

console.log(deep_equal(obj1, obj2)); // true
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // false
console.log(deep_equal([], [])); // true
console.log(deep_equal({}, {})); // true
console.log(deep_equal([], {})); // false

Und wenn Sie die Unterstützung für Function , Date y RegExp können Sie dies am Anfang von deep_equal (nicht getestet):

if ((typeof obj1 === 'function' && typeof obj2 === 'function') ||
(obj1 instanceof Date && obj2 instanceof Date) ||
(obj1 instanceof RegExp && obj2 instanceof RegExp))
{
    obj1 = obj1.toString();
    obj2 = obj2.toString();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X