Операторы сравнения в JavaScript: тройной знак равенства и двойной знак равенства
Вы видели двойные и тройные знаки равенства в JavaScript. Но что они? Если коротко: == преобразует тип, а === не преобразует тип.
Двойной знак равенства (==) проверяет только равенство значений. Он выполняет приведение типов. Это означает, что перед проверкой значений он преобразует типы переменных, чтобы привести их в соответствие друг к другу.
Тройной знак равенства (===) не выполняет приведение типов. Он проверяет, имеют ли сравниваемые переменные одинаковое значение и тип.
Рассмотрим несколько примеров:
Пример 1
const foo = "test" const bar = "test" console.log(foo == bar) //true console.log(foo === bar) //true
Значение и тип у foo и bar одинаковые. Поэтому результат для обоих — true.
Пример 2
const number = 1234 const stringNumber = '1234' console.log(number == stringNumber) //true console.log(number === stringNumber) //false
Значения number и stringNumber выглядят одинаковыми. Но number имеет тип Number, а stringNumber имеет тип string. Даже если значения переменных одинаковы, тип не совпадает. Поэтому оператор == возвращает значение true. Но при проверке значения и типа значение равно false.
Пример 3
console.log(0 == false) //true console.log(0 === false) //false
Значение 0 при проверке с false является тем же. 0 и false имеют одинаковое значение для JavaScript. Но при проверке с помощью тройного оператора значение ложно, потому что 0 имеет тип number, а false – boolean.
Пример 4
const str = "" console.log(str == false) //true console.log(str === false) //false
Значение пустой строки и false – это в JavaScript то же самое. Следовательно, == возвращает значение true. Но тип переменных отличается, поэтому === возвращает значение false.
Когда использовать ==, а когда ===?
Если есть сомнения, используйте ===. Это избавит вас от большого количества потенциальных ошибок.
Если не нужен контроль входящих данных, используйте ==. Например, если API принимает от клиента «true» и true, используйте ==.
Эта таблица показывает, насколько сложно сравнение в JavaScript.
Отличия == и === в JavaScript
В JavaScript есть два похожих оператора: == и ===. Если не знать их отличия, это может обернуться кучей ошибок. Так что решил раскрыть эту тему. Чем именно отличаются == и ===, как они работают, почему так происходит, и как избежать ошибок.
Оператор == сравнивает на равенство, а вот === — на идентичность. Плюс оператора === состоит в том, что он не приводит два значения к одному типу. Именно из-за этого он обычно и используется.
abc == undefined; // true, если abc = undefined | null abc === undefined; // true - только если abc = undefined!
abc == false; // true, если abc = false | 0 | '' | [] abc === false; // true, только если abc = false!
Ведь путать false и 0 (или », или []) — вряд ли очень хорошо.
5 === 5; // true true === true; // true 'abc' === 'abc'; // true
А теперь интересный пример.
5 == 5; // true 5 === 5; // true new Number(5) == 5; // true new Number(5) === 5; // false!
Почему так происходит? Да, любое число — это объект класса Number. Но можно представить число как цифру — некоторой константой. Она единожды объявлена, и всегда идентична сама себе. Но в то же время объявляя новый объект класса Number — он равен ей по значению, но не идентичен (так как это два совершенно разных объекта класса Number).
Arrays / Objects
А вот для массивов и объектов оба оператора работают одинаково, сравнивая на идентичность:
var a = <>; a == <>; // false a === <>; // false a == a; // true a === a; // true
Для сравнения массивов и объектов можно написать специальную функцию:
function isEq(a, b) < if(a == b) return true; for(var i in a)< if(!isEq(a[i], b[i])) return false; >for(var i in b) < if(!isEq(a[i], b[i])) return false; >return true; >
Немножко неаккуратно, два цикла, да и про hasOwnProperty забыли; ну да сойдёт.
This
Есть ещё один подводный камень. Это передача в this.
(function()< this == 5; // true this === 5; // false >).call(5);
(function()< this == 5; // true this === 5; // false >).call(5);
Вот такой вот момент. Стоит о нём не забывать.
Итого.
Ну а теперь представим, что мы пишем свой суперфреймворк, активно юзаем там оператор === вместо == просто потому что он красивее, и некто находит у нас несколько багов.
func(new Number(5)); (function()< func(this); >).call(5);
Кажется, что такие примеры нежизнеспособны? Пожалуйста!
$.each([1, 2, 3, 4, 5], function()< func(this); >);
Ну или захотелось расширить цифру.
var Five = new Number(5); Five.a = 2; // захотелось расширить, а просто 5 не расширяется // здесь как-то используем. func(Five);
На этом всё, надеюсь кому-то будет полезно. Спасибо за внимание.
UPD. Спасибо за ссылку vermilion1, JS Гарден.
- равенство
- идентичность
Двойной и тройной операторы равенства == и === Примеры
До этого момента мы имели дело только с операторами сравнения, которые использовались для принятия решений при работе с конструкциями if-else. При этом преимущественно использовался оператор >= больше или равно.
Но давайте предположим, что у нас есть два значения. И вместо того, чтобы сравнивать их: одно больше или меньше другого, нам нужно проверить , равны ли между собой эти значения .
Для этого существую различные операторы равенства.
Допусти есть переменная age = 18 . Это возраст. Составим выражение if которое будет выводить в консоль строку, если человек стал взрослым, то есть только в том случае, если возраст равен именно 18 годам.
Для этого в условии if используется тройное равенство «===» .
Оператор равенства — Три знака равно
Рассмотрим пример использования оператора тройного равенства в JavaScript и потом прокомментируем его.
Пример 1.1
const age = 18; if (age === 18)
You just became an adult
You just became an adult — Ты только что стал взрослым.
Блок if в одну строку
Оптимизируем код примера 1.1
Всякий раз, когда блок if имеет одну строку, мы можем не использовать фигурные скобки. Нам не нужно создавать этот блок <> , если мы работаем только с одной строкой. Мы можем опустить фигурные скобки. И записать все в одну строку.
Пример 1.2
const age = 18; if (age === 18) console.log('You just became an adult');
You just became an adult
Если же переменная age = 19 , то 19 уже не равно 18. И мы не увидим результата.
Пример 1.3
const age = 19; if (age === 18) console.log('You just became an adult');
Как работает тройной оператор равенства
Но вернемся к примеру 1.2 . Как работает тройной оператор равенства в JavaScript? По сути, так же, как и операторы сравнения.
Оператор равенства будет возвращать истину или ложь true или false , то есть булево значение. И true будет результатом работы этого оператора только в том случае, если обе стороны равенства содержат одно и то же.
Для удобства можно перейти непосредственно в консоль и продемонстрировать еще раз работу оператора тройного равенства.
18 === 18 true 18 === 19 false
Не стоит путать присваивание, которое представляет собой лишь один знак равенства «=» с оператором сравнения , который представляет собой тройное равенство «===» .
Двойное равенство ==
Кроме тройного равенства, в JavaScript существует еще двойное равенство «==» — два знака равно .
Разница в том, что тройное равенство является оператором строгого равенства ( strict — строгий). Потому что при этом не выполняется приведение типов . Оператор строго равенства возвращает true только, когда оба значения идентичны/точно такие же.
С другой стороны существует свободный оператор равенства ( loose — свободный), который имеет только два знака равно .
Свободный оператор равенства == (два знака равно) проводит приведение типов. Вернемся снова в консоль.
Пример 2.1
'18' == 18 true
Сравнение строки ’18’ и числа 18 дает true .
Итак, еще раз двойное равенство проводит приведение типов . Это означает, что строка ’18’ в примере конвертируется в число 18 . Поэтому 18 равно 18 и это истина true .
И, как уже упоминалось, тройное равенство не проводит приведение типов . Продолжим работать с примером:
Пример 2.2
'18' === 18 false
Та же ситуация, что и в примере 2.1, но с оператором строго равенства и мы видим false . Потому что строка ’18’ конечно же, отлична от числа 18 . Это не одно и то же и в этом случае JavaScript не конвертировал ни одной из значений.
Продолжим работать с примером №1
Пример 1.4
const age = 18; if (age === 18) console.log('You just became an adult (strict)'); if (age == 18) console.log('You just became an adult (loose)');
You just became an adult (strict) You just became an adult (loose)
В первом условии используется оператор строгого равенства, во втором двойное равенство. И в обоих случаях мы видим один и тот же результат, потому что оба условия возвращают true .
Пример 1.5
Если же в качестве значения переменной age будет строка ’18’ , то мы увидим иной результат:
const age = '18'; if (age === 18) console.log('You just became an adult (strict)'); if (age == 18) console.log('You just became an adult (loose)');
You just became an adult (loose)
Только условие с оператором двойного равенства вернуло true . Так как при этом строка ’18’ была преобразована в число 18 . Условие с оператором строго равенства вернуло false .
Всегда строгое равенство ===
Надеемся, что это не было запутанным для Вас. Ведь это довольно не простая тема в JavaScript . Потому что свободный оператор двойного равенства полон действительно странных правил и моделей поведения .
Это означает, что использование оператора двойного равенства может привести к появлению многих труднодоступных ошибок в вашем коде.
Поэтому одним из главных правил написания чистого кода является: избегать использовать оператор двойного равенства насколько это возможно.
Итак, при сравнении значений всегда используйте строгое равенство с тремя знаками равно . Большинство JavaScript разработчиков рекомендуют делать именно так. Это, несомненно, хорошее правило.
Если же вам действительно нужно преобразование типов, в этом случае делается ручная конвертация значений перед их сравнением . Это будет лучшим шагом, чем полагаться на оператор двойного равенства.
Некоторые всегда по умолчанию используют тройной оператор равенства и делают вид, что это единственный из существующих вариантов. Так будем делать и мы. Хотя о двойном операторе равенства мы еще поговорим.
Далее рассмотрим другие примеры.
Примеры использования двойного и тройного равенства
Рассмотрим пример, когда значения приходят с веб-страницы. Для этого мы будем использовать функцию prompt (понятие функций мы будем рассматривать в следующем разделе).
Пример 3.1
prompt('What is your favorite number?');
Этот код будет вызывать окно с полем для ввода информации.
В нашем случае требуется ввести какое-либо число и затем нажать ОК. ‘What is your favorite number?’ — Какое твое любимое число?
По сути, эта строка prompt(‘What is your favorite number?’); создает значение — то, которое мы введем. Но нужно это значение куда-то записать. Для этого данную строку нужно присвоить переменной.
Пример 3.2
const favorite = prompt('What is your favorite number?'); console.log(favorite); console.log(typeof favorite);
Таким образом, переменная favorite будет содержать значение, которое мы введем в поле для ввода, вызванное функцией prompt. Это значение можно как-то использовать. Например, вывести его в консоль.
Но обратите внимание: введенное число 23 имеет белый цвет в консоли . Как вы помните, это означает, что это строка . В примере, при помощи оператора typeof, мы сразу сделали проверку и увидели, к какому типу данных относится введенное число. Еще раз — это строка.
Теперь немного логики: ведь нам нужно число , а не строка.
Пример 3.3
const favorite = prompt('What is your favorite number?'); console.log(favorite); console.log(typeof favorite); if (favorite == 23) < // '23' == 23 ->TRUE console.log('Cool! 23 is a number'); >
23
string
Cool! 23 is a number
В результате выполнения этого кода мы видим сообщение о том, что 23 это число . Хотя сначала мы получаем строку. Почему так происходит? Ответ прост: при использовании оператора двойного равенства происходит приведение типов. И в результате в условии блока if строка ’23’ конвертируется в число 23 .
Если же использовать оператор строго равенства с тремя знаками равно, то этот код работать не будет .
Пример 3.4
const favorite = prompt('What is your favorite number?'); console.log(favorite); console.log(typeof favorite); if (favorite === 23) < // '23' === 23 ->FALSE console.log('Cool! 23 is a number'); >
При использовании оператора строго равенства в JavaScript не происходит приведения типов . Строка ’23’ не равна числу 23.
Пример 3.5
В этой статье уже шла речь о том, что при сравнении значений рекомендуется всегда использовать строгое равенство с тремя знаками равно . Поэтому в примере для преобразования строки в число необходимо использовать функцию Number.
const favorite = Number(prompt('What is your favorite number?')); console.log(favorite); console.log(typeof favorite); if (favorite === 23) < // 23 === 23 ->TRUE console.log('Cool! 23 is a number'); >
23
number
Cool! 23 is a number
В результате мы снова видим строку Cool! 23 is a number . Только теперь в отличие от примеров выше мы сразу имеем дело с числом 23 : это видно и по цвету числа и по типу данных number . И в итоге оператор тройного равенства это также подтверждает.
Пример 3.6
Пробуем в поле для ввода ввести другое число, например 22:
const favorite = Number(prompt('What is your favorite number?')); console.log(favorite); console.log(typeof favorite); if (favorite === 23) < // 22 === 23 ->FALSE console.log('Cool! 23 is a number'); >
Здесь мы имеем дело с числом 22 , но оно не равно 23 , поэтому код блока if не работает .
Несколько условий одновременно
Здесь мы переходим к следующему шагу, в котором добавим больше условий в конструкции if-else . Несколько условий в JavaScript — читайте об этом здесь.
Пока что/до этого момента, после блока if всегда следовал блок else. Но мы можем добавить еще блок if . Это работает так: после первого блока if пишется else, а потом снова ключевое слово if.
Пример 4.1
const favorite = Number(prompt('What is your favorite number?')); console.log(favorite); console.log(typeof favorite); if (favorite === 23) < console.log('Cool! 23 is a number'); >else if (favorite === 7) < // second 'if' console.log('7 is also cool number') >else
7 number 7 is also cool number
В целом такая конструкция с несколькими блоками if (с несколькими условиями) работает так : сначала выполняется проверка условия первого блока if. Если первая проверка не проходит, выполняется проверка условия второго блока if. Если эта проверка проходит, то выполняется код второго блока if.
В конце, после второго блока if мы можем добавить блок else, как это сделано в примере выше. Или же добавить еще один блок if — смотрим пример ниже.
Пример 4.2
const favorite = Number(prompt('What is your favorite number?')); console.log(favorite); console.log(typeof favorite); if (favorite === 23) < console.log('Cool! 23 is a number'); >else if (favorite === 7) < console.log('7 is also cool number') >else if (favorite === 11) < console.log('11 is also cool number') >else
1 number Number is not 23 or 7 or 11
Итак, в таких конструкциях, при составлении нескольких условий, блок else выполняется в последнюю очередь . Сначала проверяются все условия в блоках if, и если ни одно из них не является истинным, только тогда выполняется блок else.
На практике подобные конструкции if-else с составлением нескольких условий (несколько блоков if), время от времени используются.
Операторы неравенства
В конце этой заметки, рассмотрим оператор неравенства. Ранее мы говорили об операторе равно/равенства. Но, конечно же, должен быть оператор , который работает в обратном порядке . Итак, это оператор неравенства. И теперь давайте проверим иным способом , что если переменная favorite отлична от числа 23 .
Для этого используется восклицательный знак и двойное равенство !== . Это является строгой версией оператора неравенства . Есть также и свободная версия с одним знаком равно != .
Но как и в ситуации со знаком равенства свободной версии == (два знака равно) и строгой версии === (три знака равно): при использовании знака неравенства так же стоит придерживаться строгой версии !== .
Пример 4.3
const favorite = Number(prompt('What is your favorite number?')); console.log(favorite); console.log(typeof favorite); if (favorite === 23) < console.log('Cool! 23 is a number'); >else if (favorite === 7) < console.log('7 is also cool number') >else if (favorite === 11) < console.log('11 is also cool number') >else < console.log('Number is not 23 or 7 or 11'); >if (favorite !== 23) console.log('Why not 23?');
11 is also cool number
Здесь при помощи оператора строго неравенства !== была добавлена еще одна проверка: это еще один блок if с условием: (favorite !== 23) . Если введенное значение не равно 23, то мы увидим строку «Why not 23?» .
Итак, при составлении условий в JavaScript используется как оператор строго равенства === , так и строго неравенства !== . Просто выбирайте, что вам нужно для решения тех или иных задач.
Свободные операторы равенства == и неравенства != используются реже. И с ними стоит быть очень внимательными.
Операторы равенства == и === в JavaScript
Если вы читаете этот блог, вы, вероятно, изучаете JavaScript — и это замечательно. Двойное и тройное равно (== и ===) в JavaScript часто заставляют новичков ломать голову. Но пусть вас это не пугает: когда вы узнаете, как работают эти операторы, вы поймете, что такие особенности делают JS еще красивее.
Что такое == и === в JavaScript?
Операторы == и === используются для сравнения и определения степени равенства или идентичности сравниваемых объектов.
И двойное, и тройное равно возвращают true, если сравниваемые объекты равны, а в противном случае возвращают false. Разница между ними в том, что эти операторы используют разные критерии для определения степени равенства.
Учитывая это, давайте на примерах разберемся, чем == отличается от ===.
Как работает оператор == в JavaScript
Двойное равно (==) часто называют «нестрогим равенством», потому что этот оператор выполняет приведение типов перед сравнением.
Это означает, что если типы данных сравниваемых операндов различны, то JavaScript автоматически преобразует один из операндов в тот же тип, что и другой, чтобы их можно было сравнить.
Давайте разберемся с помощью примера.
const a = 100; const b = '100'; console.log(a == b) // true
Здесь у нас есть две переменные, a и b . Тип переменной a — число, а тип переменной b — строка.
Когда мы сравниваем эти две переменные с помощью двойного равенства, мы получаем на выходе true.
Это происходит потому, что перед сравнением переменная a приводится к строковому типу.
После преобразования значения обеих переменных сравниваются. Если они одинаковы, мы получим true, в противном случае — false. В нашем случае это true.
Важно отметить, что фактическое значение остается неизменным. Оно лишь неявно преобразуется при сравнении.
Правила приведения типов
Рассмотренный пример довольно прост, не так ли? Давайте попробуем еще один, а после разберем правила приведения типов.
const a = true; const b = 'true'; console.log(a == b)
Итак, как вы думаете, что получится на выходе? Если ваш ответ был true, то, к сожалению, это неверно. Но если вы догадались, что должно получиться false, то поздравляю.
Если ваш ответ был неправильным, не волнуйтесь, потому что сейчас мы познакомимся с несколькими правилами, которые помогут вам разобраться.
Итак, вот правила для приведения типов в JavaScript:
- Если один из операндов является строкой, то второй операнд будет преобразован в строку.
- Если один из операндов является числом, другой операнд будет преобразован в число.
- Если один из операндов является булевым значением, он будет преобразован в число (true станет 1, а false — 0).
- Если один из операндов является объектом, а другой — примитивным значением, то перед сравнением объект будет преобразован в примитивное значение.
- Если один из операндов равен null или undefined, то, чтобы при сравнении вернулось true, второй тоже должен быть null или undefined. В противном случае возвращается false.
Теперь, ознакомившись с правилом из пункта 3, вы знаете, почему в приведенном выше примере наш ответ был false.
Значение переменной a (true) перед сравнением преобразуется в число. После этого мы сравниваем 1 и «true» — и получаем false, потому что переменные содержат разные значения.
Как работает оператор === в JavaScript
Тройное равно (===), также называемое «строгим равенством», работает аналогично двойному равно. Но есть важное отличие: при использовании === типы операндов не приводятся перед сравнением.
При сравнении переменных сначала проверяется, отличаются ли их типы. Если да, то возвращается false. Если типы совпадают, то проверяется значение. Если значения одинаковы и не являются числами, возвращается true.
Наконец, если оба операнда — числа и не NaN, и у них одинаковое значение, то возвращается true. В противном случае — false.
Давайте разберемся в этом с помощью примера:
const a = 100; const b = '100'; console.log(a === b);
Мы взяли тот же пример, что и выше, но при сравнении использовали не двойное, а тройное равенство.
Итак, возможно, вы уже угадали ответ. Да, это false, а почему? Потому что тип переменной a — число, а тип переменной b — строка.
При сравнении тройное равенство сначала проверяет типы операндов, а в данном примере эти типы различаются. Поэтому возвращается false.
Давайте рассмотрим другой пример:
const a = true; const b = 1; console.log(a === b);
Здесь у нас тоже две переменные, a и b . Тип переменной a — boolean, а тип переменной b — число. Если мы будем их сравнивать с помощью строго равенства, оно вернет false — потому что, опять же, переменные имеют разные типы.
Заключение
Операторы == и === в JavaScript — это операторы сравнения, которые мы используем, чтобы определить, равны или нет два значения.
Оператор == выполняет нестрогое сравнение, при необходимости преобразуя типы, чтобы сделать сравнение возможным.
Оператор === выполняет строгое сравнение, без приведения типов. При использовании тройного равно сравниваются и типы, и значения.
Преобразование типов в JavaScript иногда может приводить к неожиданным результатам, поэтому чаще всего при сравнении рекомендуется использовать оператор строгого равенства ===.