Porównywanie obiektów niewrażliwe na kolejność kluczy

Temat dotyczący taska T862

Pierwszy pomysł to wykorzystanie jakiejś biblioteki haszującej np. object-hash: https://github.com/puleos/object-hash/. Biblioteka jest mała i domyślnie jest robust na kolejność kluczy.

Drugi pomysł, to ręczna implementacja funkcji rekurencyjnej, która albo będzie tworzyła nowy obiekt i wstawiała klucze w posortowanej kolejności (i podobnie pod-obiektów), albo będzie po prostu porównywała wartości posortowanych kluczy bez tworzenia nowego obiektu. Właściwa implementacja drugiego wariantu tej funkcji nie jest oczywista i może być wolniejsza.

Na pierwszy rzut oka nie widzę powodu, żeby to ręcznie implementować, ale może coś mi umyka, albo nie widzę lepszego rozwiązania. Można też zrobić benchmarki, ale pytanie czy to rzeczywiście będzie bottleneckiem.

Jedną z możliwych odpowiedzi na ten problem może być używanie immutables:

https://facebook.github.io/immutable-js/

Co do object-hash, czy wiemy ile on dodaje kB do wagi projektu? Jako, że to będzie logika odpalana na froncie to trzeba to mieć mocno na uwadze. Widzię, że object-hash robi require("crypto"), a crypto to jest pusty deprecated package, i nie wiem co się dzieje xD

Możesz rozwinąć to immutables? Bo nie wiem czy wiem o co dokładnie chodzi - mielibyśmy przejść z plain objects na np. Immutable.Map i używać funkcji equals()? To duża zmiana by była, chyba że tylko póki co w tym fragmencie, bo pewnie Immutable i tak nam się przyda w przyszłości?

Jeszcze sprawdzę, ale jak patrzyłem na wielkość pliku, to object-hash waży około 30kB. Na npmie jest, że niby nie ma żadnych dependencies, także dziwna sprawa xD

Sprawdziłem i zajmuje 36kB. To bardzo dużo jak na pakiet do front-endu :< Do tego wciąż nie wiem, jak oni zaciągają zależności, ale wiem że korzystają z bowera i gulpa :DDDD

Co sądzisz o czymś takim?

function objects_equal(obj1, obj2) {
	if (obj1 === obj2) {
		return true;
	}
	const keys1 = Object.keys(obj1);
	const keys2 = Object.keys(obj2);
	if (keys1.length !== keys2.length) return false;
	return keys1.every(
		objects_equal(obj1[key], obj2[key])
	);
}
> objects_equal({a: "A", b: "B"}, {b: "B", a: {ą: "Ą", a: "A"}})
false
> objects_equal({a: "A", b: "B"}, {b: "B", a: "A"})
true

Kurczę - nie wiem czemu mi się wydawało, że to będzie dużo bardziej skomplikowane. Jestem za.

1 Like

Rzecz robi się bardziej skomplikowana, gdy bierzemy pod uwagę porównywanie funkcji, prototypów itp. Ale jeżeli chcemy porównywać z dokładnością JSONową ale bez brania pod uwagę kolejności, to to powinno wystarczyć :slight_smile: