Операторы равенства и строгого равенства



При написании программного обеспечения более простое решение почти всегда является лучшим. Если для того, чтобы воспользоваться какой-то функцией, мне сначала нужно запомнить список правил, я стараюсь избегать этого. Не потому, что эта функция не может быть ценной, а потому, что я не доверяю себе в запоминании всех нюансов правил.
Вот почему я всегда использую оператор строгого равенства (===)
вместо оператора равенства (==)
. Оба оператора решают похожие задачи, но стандартные настройки строгого равенства намного удобнее для меня в качестве пользователя.
Оператор строгого равенства (тройное равенство)
При использовании тройного равенства ===
необходимо помнить два правила - строгое равенство (для сравнения примитивных значений) и ссылочное равенство (для сравнения ссылочных значений).
Строгое равенство
Строгое равенство проверяет, что тип (число, строка, булево и т.д.) и значение одинаковы:
- Если и значение, и тип одинаковы, получим
true
. - Если тип одинаков, но значение разное, получим
false
. - Если значение одинаково, но тип разный, получим
false
.
5 === 5 // true. Одинаковый тип и значение
5 === 4 // false. Тип одинаковый, значения разные
5 === "5" // false. Значение одинаковое, тип разный.
true === true // true. Одинаковый тип и значение
true === false // false. Тип одинаковый, значения разные
true === 'true' // false. Значение одинаковое, тип разный.
Кажется достаточно простым. Но есть нюанс. Это правило нарушается, когда мы начинаем сравнивать объекты (ссылочные типы), а не примитивы.
Ссылочное равенство
Как мы видели в предыдущем примере, примитивы сравниваются по значению. При использовании тройного равенства для сравнения объектов будут сравниваться ссылки (участки в памяти).
{} === {} // false. Одинаковый тип, одинаковое значение, разная ссылка на участок в памяти. ❌
[] === [] // false. Одинаковый тип, одинаковое значение, разная ссылка на участок в памяти. ❌
{ name: 'Meg' } === { name: 'Meg' } // false. Одинаковый тип, одинаковое значение, разная ссылка на участок в памяти. ❌
Каждый из приведенных примеров имеет один и тот же тип, и как будто одинаковое значение. Но, у объектов используется ссылочное значение — JavaScript сравнивает ссылки на участки в памяти, а не фактическое значение. В каждом из примеров эти ссылки и местоположение в памяти различны, поэтому всегда получаем false
.
Рассмотрим пример. Присвоим двум переменным одну и ту же ссылку в памяти, а затем применим к ним оператор тождества.
const user = { name: "Mark" };
const person = user;
console.log(user === person); // true
person.name = "Вася Пупкин";
console.log(user === person); // true
console.log(user.name); // "Вася Пупкин"
И person
, и user
ссылаются на одно и то же место в памяти, поэтому получаем true
.
Если вы знаете про равенство ссылочных типов, то в с оператором тождества (===)
все работает так, как вы ожидаете. Вот таблица равенства, чтобы доказать это:

Оператор равенства (двойное равенство)
Оператор равенства (==) же ведет себя не так, как вы ожидаете (только если вы не знакомы с ним очень хорошо).
"1" == 1 // true
null == undefined // true
0 == '' // true
'0' == false // true
[1] == true // true
Что здесь происходит? Обратите внимание — каждое сравнение выполняется между разными типами. В случае строгого равенства (===)
, все они вернут false
, так как все они относятся к разным типам. С оператором равенства (==)
все не так просто. Вместо того, чтобы возвращать false
при несовпадении типов, он пытается преобразовать их в один тип.
Почему "1" == 1
возвращает true
? JavaScript видит оператор равенства, видит разные типы, преобразует строку "1" в число 1, чтобы сравнить. Получается 1 == 1
, что является истиной.
Именно этап приведения типов делает оператор равенства (==) таким непредсказуемым. В качестве доказательства приведу ту же таблицу, только теперь для обычного равенства (==)
:

Если вы, как и другие разработчики вашей команды, в совершенстве знаете все правила принудительного согласования типов JavaScript, можете смело использовать оператор равенства (==)
. Если вы похожи на меня и предпочитаете использовать инструмент, который работает так, как вы ожидаете, придерживайтесь оператора тождества (===)
.