2016-07-29 2 views
1

Я использую функцию lodash isEqual для глубокого сравнения объектов JavaScript. Это требует объектов, чтобы иметь одни и те же прототип считаются равным, а на следующую сессию с узлом РЕПЛ показывает:Проверка js глубокого равенства без учета прототипов (желательно в lodash)

> const isEqual = require('lodash').isEqual 
undefined 
> isEqual({a:3},{a:3}) 
true 
> class Foo { constructor(x) {this.a = x} } 
[Function: Foo] 
> isEqual(new Foo(3), new Foo(3)) 
true 
> isEqual({a:3}, new Foo(3)) 
false 

Есть простой способ сделать глубокое сравнение прототипов не учитывая? Он должен по-прежнему проводить специальное сравнение для дат; Я просто хочу, в случаях, когда lodash будет делать рекурсивное сравнение, что неважно, отличаются ли прототипы. Очевидно, я мог бы сам его закодировать, но я использовал lodash, чтобы не делать этого. Я также думал о том, чтобы делать

isEqual(JSON.parse(JSON.stringify(obj1)), JSON.parse(JSON.stringify(obj2))) 

Возможно, все в порядке, но кажется грубым.

+0

Вы можете просто использовать 'JSON.stringify ({а: 3}) === JSON.stringify (новый Foo (3)) 'в последнем примере; – user3335966

+0

Это не работает. Большинство браузеров дадут разные результаты для 'JSON.stringify ({a: 1, b: 2})' и 'JSON.stringify ({b: 2, a: 1})'. – gmr

ответ

0

Это не "простой путь", но это может помочь:

function eq(a, b){ 
    if(!_.isObject(a) || !_.isObject(b)) return 'Error! Only for objects.'; 
    var keysA = Object.keys(a).sort(); 
    var keysB = Object.keys(b).sort(); 
    if(!_.isEqual(keysA, keysB)) return false; 
    for(var i = 0, l = keysA.length; i < l; i++){ 
     if(
      (_.isObject(a[keysA[i]]) && _.isObject(b[keysB[i]]) && !eq(a[keysA[i]], b[keysB[i]])) || 
      (!_.isObject(a[keysA[i]]) && !_.isObject(b[keysB[i]]) && a[keysA[i]] !== b[keysB[i]]) || 
      (_.isObject(a[keysA[i]]) !== _.isObject(b[keysB[i]])) 
     ) return false; 
    } 
    return true; 
} 

eq({a: 1}, new Foo(1));   //true 
eq({a: 1}, new Foo(2));   //false 
eq({a: 1, b: 2}, {b: 2, a: 1}); //true 
eq({a: 1, b: 3}, {b: 2, a: 1}); //false 

eq({a: {a: 1}}, {a: new Foo(1)})//true 
+0

Спасибо. Мне кажется, что это решение сломается на Датах, и, возможно, в других случаях я не рассматривал (а может и нет). Я думаю, что если бы я пошел по пути определения более сложной функции, подобной этой, я бы либо начал с реализации lodash, либо модифицировал ее, либо, возможно, сделал что-то, основанное на функции lEADAS 'isEqualWith'. Кроме того, я видел некоторые «канонические функции JSON.stringify», которые заказывают ключи. На данный момент, однако, «грубое» решение, о котором я говорил, похоже, работает нормально, поэтому я придерживаюсь этого, пока это не дает мне проблем :) – gmr

Смежные вопросы