2015-08-01 12 views
5

Ho un'API e voglio affermare che almeno i dati previsti vengono restituiti. Non mi interessa se vengono restituiti più dati.Come affermare oggetti parzialmente uguali/confronta in javascript?

Perciò voglio mettere a confronto due oggetti (expected e actual) dove tutti gli attributi di expected devono essere uguali a actual, ma actual può contenere più attributi:

var expected = { 
    foo: 1, 
    bar: { 
     x1: 42, 
     a1: [ 
      1, 
      2, 
      { 
       x: 7 
      } 
     ] 
    } 
} 

var actual = { 
    foo: 1, 
    whatever: 55, // to be ignored 
    additional: { // to be ignored 
     ignore: 1 
    }, 
    bar: { 
     x1: 42, 
     a1: [ 
      1, 
      2, 
      { 
       x: 7, 
       y: 8 // to be ignored 
      } 
     ] 
    } 
} 

partiallyEqual(expected, actual) // returns true 

qualche altro esempio:

partiallyEqual({x: 1}, {a:2, x:1}) // return true 
partiallyEqual({x: 1}, {a:2, x:2}) // return false (x is different) 

Gli array possono (facoltativamente) essere soggetti a un equivalente parziale, se actual contiene elementi aggiuntivi.

partiallyEqual([1, 3], [1, 2, 3]) // return true 
partiallyEqual([3, 1], [1, 2, 3]) // return false (different order) 
+1

Hai provato 'deepEqual' Chai? – Gyandeep

+0

sì, ma è un uguale rigoroso, id non ignora alcun attributo –

+0

Dal momento che il tuo caso d'uso è una piccola variante di 'deepEqual', ti suggerisco di guardare qui: https: //github.com/chaijs/deep-eql /blob/master/lib/eql.js Modificalo un po 'per il tuo bisogno. – Gyandeep

risposta

0

Io uso questa funzione ricorsiva, che ho scritto qualche tempo fa:

Object.prototype.equals = function(to) { 
    for (var prop in to) { 
     if (this.hasOwnProperty(prop) && to.hasOwnProperty(prop)) { 
      if (to[prop] && typeof this[prop] == "object" && typeof to[prop] == "object") { 
       if (!this[prop].equals(to[prop])) { 
        return false 
       } 
      } else if (this[prop] != to[prop]) { 
       return false 
      } 
     } 
    } 
    return true; 
}; 

({ x: { a: 1, b: 2 } }).equals({ x: { a: 1, b: 2 } }) => true 
({ x: { a: 1, b: 2 } }).equals({ x: { a: 1, b: 1 } }) => false 
({ x: [1,2] }).equals({ x: { 1:1,2:2 } }) => true (doesn't differentiate between array and/or object) 

Questa funzione restituisce falso non appena trova qualche differenza nella vecchia vs nuovo oggetto. Il nuovo oggetto può contenere qualsiasi cosa, se ha tutte le proprietà del vecchio oggetto.

+0

Si prega di vedere [Come definire il metodo in javascript su Array.prototype e Object.prototype in modo che non compaia in for in loop] (http://stackoverflow.com/a/13296897/1048572) e fare l'oggetto ' estensione .prototype' correttamente. – Bergi

+1

Io uso funzione denominata prop che lo fa: la funzione prop (a, nome, func) { 'Object.defineProperty (to.prototype, nome, { valore: func, scrivibile: vero, configurabile: true} ) ; return func; } ' è usato come daini ' prop (oggetto, 'uguale', la funzione (a) {...}) ' questi possono essere concatenati: ' prop (oggetto, 'è uguale a', la funzione (per) {prop (Array, 'equals', function (to) {...})}) E a proposito, l'estensione dell'oggetto estende anche Array, poiché estende TUTTO – Akxe

0

L'equalizzazione profonda può essere complicata per vari casi, ad esempio NaN !== NaN e potrebbero esserci riferimenti circolari. Ho scritto una semplice funzione di util equal check deep con controlli di riferimento circolari e ricorsivi recentemente, e dovrebbe essere abbastanza semplice da seguire. Puoi semplicemente ignorare parte del controllo della lunghezza per fare in modo che il lavoro sia parzialmente uguale.

codice sorgente su GitHub: https://github.com/ryancat/simple-deep-equal

Problemi correlati