В JavaScript, если вы работаете с массивами или объектами, вы можете столкнуться с чем-то странным. Если у вас есть два одинаковых массива или объекта и вы попытаетесь проверить, одинаковы ли они, вы получите «false».

[1, 2, 3] === [1, 2, 3];
//Returns "false"

[1, 2, 3] == [1, 2, 3];
//Returns "false"

let object1 = {make: "Ford", model: "F150", color: "white"};
let object2 = {make: "Ford", model: "F150", color: "white"};
object1 === object2;
//Returns "false"

object1 == object 2;
//Returns "false"

Это может показаться бессмысленным, особенно если учесть следующее:

object1 = object2;
object1 === object2;
//Returns "true"

Если бы вы проверяли эквивалентность со многими другими типами данных, вы всегда получали бы истину. Единственные типы данных, которые имеют эту проблему, — это NaN, массивы, объекты и функции (даже если возвращаемое значение функций одинаково).

Это связано с тем, что строки, числа, нулевые значения, неопределенные значения и логические значения являются примитивными, а большинство других (кроме NaN) — нет.

Примечание. Проблема NaN != NaN немного сложнее. Но о том, что я думаю об этом, я расскажу позже.

Вместо того, чтобы вдаваться в то, как JavaScript ссылается на значения, я бы предпочел обсудить, как я думаю об этой проблеме, чтобы, возможно, помочь кому-то новому (например, мне) осмыслить разницу.

Скажем, мы описываем двух однояйцевых близнецов. Можно сказать, что у них обоих карие глаза, черные волосы и обувь 12-го размера. Ведь они идентичны. Записав их как объекты, мы можем иметь:

const tom = {hair: "black", eyes: "brown", shoeSize: 12};
const jerry = {hair: "black", eyes: "brown", shoeSize: 12}; 

Том и Джерри не один и тот же человек, но

tom.hair === jerry.hair;
//Returns "true"

tom.eyes === jerry.eyes;
//Returns "true"

tom.shoeSize === jerry.shoeSize;
//Returns "true"

tom === jerry;
//Returns "false"

Черные волосы — это черные волосы, карие глаза — это карие глаза, а размер 12 футов — это размер 12 футов, независимо от того, на ком они одеты.

Если однажды Джерри решит покрасить волосы в фиолетовый цвет, то это описание изменится, но не повлияет на Тома. Тогда у Тома не будет фиолетовых волос, и он останется Томом, на которого решение Джерри совершенно не повлияет.

И это оставляет NaN. Что случилось с NaN?

Ну, NaN может быть чем угодно и не говорит вам, что это такое. Он просто говорит вам, что это не число.

Если бы я сказал вам, что у меня нет рыжих волос и что у моего соседа тоже нет рыжих волос, у вас все равно не было бы информации о том, какого цвета у нас волосы. У вас недостаточно информации, чтобы решить, действительно ли у нас волосы одного цвета или нет, поэтому вы не можете вернуть «правда» без дополнительной информации. Вот крайний пример:

const notANumber = 0/0;
notANumber;
//Returns NaN

notANumber === notANumber;
//Returns "false"

Мы знаем, что 0/0 — это не число. Это то, что сохраняет компьютер, и это единственное, что мы о нем знаем.

Чем это отличается от «null» или «undefined»?

Для нулевых значений ничто — это то же самое, что и ничто. Нет никакой разницы между тем, что я ничего не держу в правой руке, и тем, что я ничего не держу в левой руке. Вы не можете различить их, если вы не философ или ученый, а компьютеры ни то, ни другое.

Неопределенные значения — это просто слова, которые не были определены. Слова «jellyflops» и «squimblegloop» — это слова, но неопределенные. У них точно такое же значение (отсутствие смысла), поэтому они функционально идентичны.