Sto implementando una funzione che confronta due oggetti JavaScript per l'uguaglianza "profonda". Lo scheletro di questa funzione, in questo momento, si presenta così:Rileva se il riferimento ciclico nell'oggetto A è strutturalmente uguale al riferimento ciclico nell'oggetto B
function check_equal(actual, expected) {
var stack = [];
function check_equal_r(act, exp) {
if (is_scalar(act) || is_scalar(exp)) {
assert(act === exp);
} else if (stack.indexOf(act) == -1) {
assert(have_all_the_same_properties(act, exp));
stack.push(act);
for (var k of Object.getOwnPropertyNames(exp)) {
check_equal_r(act[k], exp[k]);
}
stack.pop(act);
} else {
// ??? cyclic reference detected
}
}
check_equal_r(act, exp);
}
La domanda è: cosa mettere in cui si dice // ??? cyclic reference detected
. Idealmente, vorrei poter dire che questi oggetti sono profonde-uguali:
var a = {foo:1, bar:2, baz:null},
b = {foo:1, bar:2, baz:null};
a.baz = a;
b.baz = b;
e questi oggetti sono non deep-equal:
var a = { car: 1, cdr: { car: 2, cdr: null } };
var b = { car: 1, cdr: { car: 2, cdr: null } };
a.cdr.cdr = a;
b.cdr.cdr = b.cdr;
Note:
assert
genera un'eccezione se il suo argomento è falso.have_all_the_same_properties(x, y)
genera un'eccezione se gli elenchigetOwnPropertyNames
dix
e non sono identici.is_scalar(x)
è efficace uguale atypeof x !== 'object'
.- Ho usato un ciclo for-of nel codice di cui sopra per brevità, ma le funzioni ES6 sono non disponibili nell'interprete su cui verrà effettivamente eseguito.
Significa che 'is_scalar (x)' è lo stesso di 'typeof x! == 'object''? –
Temo di non avere molto tempo per dargli una possibilità, ma il modo in cui mi avvicino è, durante la tua operazione ricorsiva, mantenere una pila anche per 'exp'. Quando trovi inaspettatamente una corrispondenza 'indexOf' come stai facendo, * confronta quell'indice numerico *. (Se gli oggetti sono gli stessi fino ad ora, un indice di corrispondenza indica la stessa struttura) – Katana314
@ChrisHunt Er, sì, intendevo '! ==' lì. Non è esattamente * lo stesso * ma la differenza non ha importanza per lo scopo di questa domanda - ad es. nella versione completa di questo codice, gli oggetti 'Date' vengono confrontati con' getTime() '. – zwol