Сам мой вопрос таков:
Как правильно сравнивать два объекта в
javascript
?
$(document).ready(function(){
function p(o){
return JSON.stringify(o)
}
function compare(o1, o2){
const r = (o1 === o2)
console.log(p(o1) + ' === ' + p(o2) + ': ' + r)
}
var a = [], b = [], c = a;
var x = {}, y = {}, z = x;
compare(a, b) // false
compare(a, c) // true
compare([], []) // false
compare({}, {}) // false
compare(99, 99) // true
compare(new Number(1), 1) // false
compare(new Number(1), new Number(1)) // false
compare(new String('o'), new String('o')) // false
compare(new String('s'), 's') // true
compare('foo', 'foo') // true
compare({'foo':'bar'}, {'foo':'bar'}) // false
compare(x, y) // false
compare(x, z) // true
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Я хорошо понимаю, что в предыдущем фрагменте примитивныеobjetos
типы возвращаются правильно :true
console.log((9 === 9)) // true
Но хотелось бы знать, помимо умения правильно сравнивать два объекта, почему так происходит...
console.log(([] === [])) // false
ОБНОВИТЬ:
Сравнение объектов насквозь JSON.stringify()
исключено, в следующем примере вы можете увидеть, насколько эти два объекта одинаковы, единственная их вариация — это положение их элементов , поэтому при их сравнении будет возвращаться false
:
var a = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
var b = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
console.log(a === b); // true
var x = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
var y = JSON.stringify({
"lastName": "Richardson",
"firstName": "JP"
});
console.log(x === y); // false
Прямой ответ
Чтобы сравнить, являются ли два объекта «близнецами», сначала определите, являются ли они «потомками» одного и того же «родителя», а затем определите, имеют ли они одинаковую «ДНК», т. е. объекты являются экземплярами одного и того же объекта, а свойства являются одинаковые (имя, порядок, атрибуты и значения).
Если вы не заинтересованы в том, чтобы они были «близнецами», а только в том, чтобы некоторые элементы были одинаковыми, сравните эти элементы.
Вот краткий пример того, как узнать, являются ли два объекта экземплярами одного и того же объекта и, для краткости, имеют ли они одинаковые свойства, что означает, что свойства обоих имеют одно и то же имя и что их положение одинаково.
Объяснение
Необходимость сравнения определяется целью, а в случае JavaScript тем более.
По сравнению с другими языками программирования JavaScript можно считать очень гибким, поскольку алгоритмы выполнения операций учитывают типы операндов.
Учитывая вышеизложенное, при реализации сравнения в JavaScript мы должны помнить:
Учитывая вышеизложенное, а также предпосылку гибкости языка, JavaScript включает два типа сравнений, строгое и абстрактное, каждое из которых имеет собственный алгоритм, описанный в спецификациях ECMAScript. Ниже приведены ссылки на соответствующие разделы версии 5.
В итоге
Строгое сравнение двух объектов возвращает false, поскольку это указано в спецификации. Логика этого аналогична юридической идентичности «близнецов» в «западных» странах, хотя у них одни и те же родители, каждый зарегистрирован под другим именем, и каждый имеет права и обязанности как независимые лица в соответствии со своими индивидуальными условия. .
Результат абстрактного сравнения двух объектов «сбивает с толку», потому что он варьируется в зависимости от типа объектов.
Я предполагаю, что мы говорим о сравнении значений , которые хранят два объекта. В этом случае то, что упоминает @M.Gress, действительно только в том случае, если оба объекта идентичны даже в порядке их свойств , что не очень полезно. Идеальным способом было бы сравнение всех свойств, даже неперечислимых, но это невозможно, по крайней мере, не во всех браузерах.
В самой темной части JavaScript, где царит зло и неразбериха, есть две группы операторов сравнения:
В строгую группу входят операторы
===
и!==
, в то время как в нестрогую группу входят, как сказал бы учитель Дуглас Кокфорд в своей книге «JavaScript: хорошие стороны», их злые близнецы==
и!=
. Этой последней группы следует избегать любой ценой, потому что они являются причиной многих головных болей.нестрогая группа
Эту группу операторов равенства следует по возможности избегать, более того, я бы рекомендовал вам забыть об их существовании. Ключевым моментом для понимания источника проблем при использовании операторов является следующее: сравнение на равенство в JavaScript не является транзитивным . Что это значит? Давайте посмотрим на это в следующем коде:
Почему сравнение между
foo
иfoo3
приводит к томуfalse
, что они равны?Что ж, ответ немного сложен. Чтобы понять, почему это происходит, нам нужно понять , как выполняется внутреннее сравнение .
Что это значит? Это означает следующее. Если вы сравниваете две переменные, которые не являются объектами, если они внутренне различны, они преобразуются в числа с помощью
ToNumber
, а затем выполняется строгое сравнение . Вот почему это верно:Это также относится к логическим значениям, поскольку логическое значение в десятичном представлении будет равно 0 или 1. Однако при сравнении переменной X с объектом или двумя объектами происходит нечто иное: здесь операнд A или B (в зависимости от того, какой объект) оценивается с помощью
ToPrimitive
, это внутренний метод просто делает рекурсивные вызовыtoString
иvalueOf
для получения некоторого примитивного значения. Впоследствии он используетToNumber
для выполнения сравнения.Если вы сравниваете два объекта, в основном оператор нестрогого равенства возвращает true, когда они сравнивают одну и ту же ссылку в памяти:
строгая группа
Здесь обходных путей нет, сначала проверяется, что это один и тот же тип данных, затем сравниваются значения.
Как сравнить два объекта?
Если говорить о литеральных объектах и сравнении их собственных свойств , то достаточно перебрать свойства обоих объектов. Например: