Какой оператор равенства (== vs ===) следует использовать в сравнениях JavaScript?

5665

Я использую JSLint, чтобы пройти через JavaScript, и он возвращает много предложений о замене ==(два знака равенства) на ===(три знака равенства) при выполнении таких вещей, как сравнение idSele_UNVEHtype.value.length == 0внутри ifоператора.

Есть ли выигрыш в производительности для замены ==на ===?

Любое улучшение производительности будет приветствоваться, поскольку существует много операторов сравнения.

Если преобразование типов не происходит, будет ли выигрыш в производительности ==?

bcasp
источник
134
Кому это может быть интересно по той же теме === vs ==, но по PHP, можете прочитать здесь: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/…
Marco Demaio
257
На всякий случай, если кому-то интересно в 2012 году: ===это намного быстрее, чем ==. jsperf.com/comparison-of-comparisons
Ry-
25
@minitech это должно быть так, как это не делает преобразование типов
Umur Kontacı
19
@minitech, я сомневаюсь, что кто-нибудь сделает свое приложение заметно быстрее, используя ===over ==. На самом деле, тест не показывает большой разницы между обоими в современных браузерах. Лично я обычно использую ==везде, если мне действительно не нужно строгое равенство.
Лоран
5
Вот часть выступления Крокфорда JS The Good Parts, где он обсуждает операторы ===and ==: youtube.com/… Если он не играет, он в 15:20
davidhiggins

Ответы:

6488

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

Ссылка: Учебник по Javascript: Операторы сравнения

==Оператор сравнения равенства после выполнения любых необходимых преобразований типов . ===Оператор не делать преобразование, так что, если два значения не одного типа ===будет просто вернуться false. Оба одинаково быстры.

Процитирую превосходный JavaScript Дугласа Крокфорда : Хорошие части ,

В JavaScript есть два набора операторов равенства: ===и !==, и их злые близнецы ==и !=. Хорошие работают так, как вы ожидаете. Если два операнда имеют одинаковый тип и имеют одинаковое значение, то ===производит trueи !==производит false. Злые близнецы поступают правильно, когда операнды относятся к одному и тому же типу, но если они относятся к разным типам, они пытаются привести значения. правила, по которым они это делают, сложны и не запоминаются. Вот некоторые из интересных случаев:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

Сравнительная таблица равенства

Отсутствие транзитивности вызывает тревогу. Мой совет - никогда не использовать злых близнецов. Вместо этого всегда используйте ===и !==. Все приведенные сравнения производятся falseс ===оператором.


Обновить:

Точка хорошо воспитана @Casebash в комментариях и в @Phillipe Laybaert в ответ объектов относительно. Для объектов ==и ===действовать последовательно друг с другом (за исключением специального случая).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

Особый случай - когда вы сравниваете примитив с объектом, который оценивает тот же примитив, из-за его toStringили valueOfметода. Например, рассмотрим сравнение строкового примитива со строковым объектом, созданным с помощью Stringконструктора.

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Здесь ==оператор проверяет значения двух объектов и возвращает их true, но ===видит, что они не одного типа, и возвращает false. Какой из них правильный? Это действительно зависит от того, что вы пытаетесь сравнить. Мой совет - полностью обойти вопрос и просто не использовать Stringконструктор для создания строковых объектов из строковых литералов.

Ссылка
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

Билл Ящерица
источник
237
=== не быстрее, если типы одинаковы. Если типы не совпадают, === будет быстрее, потому что не будет пытаться выполнить преобразование.
Билл Ящерица
521
=== никогда не будет медленнее, чем ==. Они оба выполняют проверку типов, поэтому === ничего не делает по сравнению с ==, но проверка типов может позволить === завершиться раньше, если типы не совпадают.
Билл Ящерица
246
Замена всех == /! = На === /! == увеличивает размер файла js, тогда загрузка займет больше времени. :)
Марко Демайо
92
«... правила, по которым они делают, являются сложными и не запоминающимися ...» Теперь такие заявления заставляют вас чувствовать себя в безопасности при программировании ...
Йохан
47
От Крокфорда: «Отсутствие транзитивности вызывает тревогу». Если вы разрабатываете программное обеспечение и не обнаруживаете недостаток транзитивности в операторе сравнения, вызывающем тревогу, или если сравнение скорости между == и === или размер файла / время загрузки имеют приоритет перед переходным детерминизмом поведения оператора сравнения, вы возможно, придется вернуться и начать все сначала.
Джинглстхула
1144

Использование ==оператора ( Равенство )

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

Использование ===оператора ( личность )

true === 1; //false
"2" === 2;  //false

Это связано с тем, что оператор равенства ==выполняет приведение типов , что означает, что интерпретатор неявно пытается преобразовать значения перед сравнением.

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

Kalpesh Rajai
источник
9
@Software Monkey: не для типов значений (число, логическое значение, ...)
Филипп Лейберт
34
Поскольку никто не упомянул СТОЛ Javascript Равенства, здесь: dorey.github.io/JavaScript-Equality-Table
полыхают
6
В первом утверждении, вы уверены, что «истина» преобразуется в 1, а не 1 преобразуется в истину?
Шади Намрути
2
Откуда берутся термины «равенство» и «идентичность»? Стандарт не использует эти термины. Он называет ==«абстрактное равенство» и ===«строгое равенство». Разумеется, называть ==любое равенство имхо ужасно, поскольку оно не транзитивно, но зачем спорить? Я беру больше проблем с «идентичностью», хотя; Я думаю, что этот термин довольно вводит в заблуждение, хотя он «работает». А если серьезно, кто придумал термин «идентичность»? Я ищу стандарт и не смог его найти.
Рэй Тоал
1
«Идентичность» - очень неправильное слово. Сравнение идентичности во всех языках, которые я использовал, означает одно в одном и том же объекте , то есть две ссылочные переменные указывают не только на эквивалентные объекты, но и на одну и ту же сущность.
Иниго
724

Интересное наглядное представление сравнения равенства между ==и ===.

Источник: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

При использовании ===для проверки равенства JavaScript все как есть. Ничто не преобразуется перед оценкой.

Оценка равенства === в JS


var1 == var2

При использовании ==для проверки на равенство JavaScript происходят некоторые интересные преобразования.

Оценка равенства == в JS

Мораль истории:

Используйте, ===если вы не полностью понимаете конверсии, которые происходят с ==.

загвоздка
источник
3
@mfeineis вы имеете в виду === или! == вместо == или! =. Не хочу путать новых кодеров;)
katalin_2003
2
Исходя из моего опыта, использование трех равных может вызвать проблемы, и их следует избегать, если они полностью не поняты. два равенства дают намного лучшие результаты, потому что 99% времени я действительно не хочу, чтобы типы были равны.
vsync
13
@vsync: Если вы действительно не хотите, чтобы типы были одинаковыми , вы должны использовать три равенства !
SNag
7
Единственное исключение: вы можете безопасно использовать, x == nullчтобы проверить, xявляется ли nullили undefined.
Энди
1
@ user648026: Речь идет о сравнении равенства с ==против ===. Прописные и строчные буквы в любом случае неравны и будут возвращаться falseкак с операторами, так ==и с ===операторами. Кроме того , ключевые слова true, false, undefined, null, Infinityсуществуют в JS только в одном случае, и не могут быть использованы в верхних или смешанных случаях.
SNag
609

В ответах здесь я ничего не читал о том, что значит равный . Некоторые скажут, что это ===означает « равный» и «того же типа» , но это не совсем так. Фактически это означает, что оба операнда ссылаются на один и тот же объект или, в случае типов значений, имеют одинаковое значение .

Итак, давайте возьмем следующий код:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Тут то же самое:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Или даже:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Такое поведение не всегда очевидно. В этой истории есть нечто большее, чем быть равными и быть однотипными.

Правило таково:

Для типов значений (чисел):
a === b возвращает true, еслиaиbимеют одинаковое значение, и имеют одинаковый тип

Для ссылочных типов:
a === b возвращает true еслиaиbссылается на точно такой же объект

Для строк:
a === b возвращает true, еслиaиbявляются строками, и содержат одинаковые символы


Струны: особый случай ...

Строки не являются типами значений, но в Javascript они ведут себя как типы значений, поэтому они будут «равны», когда символы в строке одинаковы и имеют одинаковую длину (как объяснено в третьем правиле)

Теперь становится интересно:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

Но как насчет этого?

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

Я думал, что строки ведут себя как типы значений? Ну, это зависит от того, кого вы спрашиваете ... В этом случае a и b не одного типа. aимеет тип Object, а bимеет тип string. Просто помните, что создание строкового объекта с помощью Stringконструктора создает что-то типа, Objectкоторый большую часть времени ведет себя как строка .

Филипп Лейбер
источник
6
activa: Я хотел бы уточнить, что строки настолько равны только тогда, когда они являются литералами. new String ("abc") === "abc" - false (согласно моим исследованиям).
Лоуренс Дол
3
new Number() == "0", Также в Firefox:(function(){}) == "function () {\n}"
Томас Эдинг
3
Спасибо, что объяснили почему new String("123") !== "123". Они разных типов. Простой, но запутанный.
Styfle
21
Stringобъекты ведут себя как строки, как и любой другой объект . new Stringникогда не должен использоваться, поскольку это не создает настоящие строки. Настоящая строка и может быть сделана со строковыми литералами или вызываться Stringкак функция без new , например:String(0); //"0", Real string, not an object
Esailija
6
Но в случаях, которые вы подробно описали, оператор "==" ведет себя точно так же.
Ярон Леви,
270

Позвольте мне добавить этот совет:

Если сомневаетесь, прочитайте спецификацию !

ECMA-262 - это спецификация языка сценариев, для которого JavaScript является диалектом. Конечно, на практике важнее то, как ведут себя наиболее важные браузеры, чем эзотерическое определение того, как что-то должно обрабатываться. Но полезно понять, почему новая строка («а»)! == «а» .

Пожалуйста, позвольте мне объяснить, как прочитать спецификацию, чтобы прояснить этот вопрос. Я вижу, что в этой очень старой теме никто не дал ответа на очень странный эффект. Так что, если вы можете прочитать спецификацию, это очень поможет вам в вашей профессии. Это приобретенный навык. Итак, продолжим.

Поиск в файле PDF для === приводит меня к странице 56 спецификации: 11.9.4. Оператор строгого равенства (===) , и после просмотра спецификации я нахожу:

11.9.6 Алгоритм
сравнения строгого равенства Сравнение x === y, где x и y - значения, дает истину или ложь . Такое сравнение выполняется следующим образом:
  1. Если Type (x) отличается от Type (y), вернуть false .
  2. Если Тип (x) не определен, верните true .
  3. Если Тип (x) равен Null, вернуть true .
  4. Если тип (x) не является числом, перейдите к шагу 11.
  5. Если x равен NaN , верните false .
  6. Если y равен NaN , вернуть false .
  7. Если x совпадает с y, верните true .
  8. Если x равен +0, а y равен −0, вернуть true .
  9. Если x равен −0, а y равен +0, верните true .
  10. Вернуть ложь .
  11. Если Type (x) - String, тогда вернуть true, если x и y - это абсолютно одинаковая последовательность символов (одинаковая длина и одинаковые символы в соответствующих позициях); в противном случае верните false .
  12. Если Type (x) - логическое значение, вернуть true, если x и y оба - true или оба false ; в противном случае верните false .
  13. Верните истинуесли x и y ссылаются на один и тот же объект или если они ссылаются на объекты, соединенные друг с другом (см. 13.1.2). В противном случае верните false .

Интересным является шаг 11. Да, строки обрабатываются как типы значений. Но это не объясняет, почему новая строка («а»)! == «а» . У нас есть браузер, не соответствующий ECMA-262?

Не так быстро!

Давайте проверим типы операндов. Попробуйте сами, обернув их в typeof () . Я обнаружил, что новая строка ("a") является объектом, и используется шаг 1: вернуть false, если типы различаются.

Если вам интересно, почему new String ("a") не возвращает строку, как насчет упражнения по чтению спецификации? Радоваться, веселиться!


Aidiakapi написал это в комментарии ниже:

Из спецификации

11.2.2 Новый оператор :

Если Type (конструктор) не является Object, генерировать исключение TypeError.

Другими словами, если бы String не был типа Object, его нельзя было бы использовать с оператором new.

new всегда возвращает Object, даже для конструкторов String . И увы! Семантика значения для строк (см. Шаг 11) теряется.

И это, наконец, означает: новая строка («а»)! == «а» .

nalply
источник
Результат типа (x) подразумевается как typeof?
DFR
@nalply Я не совсем понимаю беспокойство по поводу поведения new String('x'), потому что я никогда не видел ни одного кода в дикой природе, который использует примитивные объекты-обертки, и я не думаю, что есть много веских причин, особенно в наши дни. Вы когда-нибудь сталкивались с кодом, который делает?
Энди
@ Если проблема злонамеренная или просто неряшливый сторонний код, то вы не можете предположить, что никто не использует new String().
nalply
Если это небрежно, ===, как вы узнаете. Если это злонамеренно, я думаю, что new String()это меньше всего из ваших забот. Я понимаю проблему в теории, но, опять же, у вас есть примеры из реальной жизни? Для меня это как старая тревога, что кто-то может установить undefinedдругую ценность.
Энди
Я не знаю, откуда вы это взяли, но ваш алгоритм сравнения ошибается на шаге 2. В разделе «7.2.15 Сравнение строгого равенства» сначала проверяется, совпадают ли типы, если да, то являются ли они Number. Если нет, то используется раздел «7.2.12 SameValueNonNumber (x, y)».
Rusty Core
101

В PHP и JavaScript это оператор строгого равенства. Это означает, что он будет сравнивать как тип, так и значения.

Shiki
источник
10
@ Дэвид: правильно. Вот почему этот ответ является неточным (или даже неправильным)
Филипп Лейберт
7
@David var a = {}, b = {}; a == bвозвращает false.
nyuszika7h
6
Да: два разных объекта с одинаковым типом и значением сравнивают false, т. Е. Этот ответ неверен. Почему у него 50 голосов?
Алексис
4
Я понимаю, что это старо, но прояснить, почему этот ответ по-прежнему «правильный», потому что в примере « var a = {}, b = {};Хотя и то, aи bдругое действительно является объектом, но с технической точки зрения они не одинаковы» . Это разные экземпляры. Обратите внимание, что сравнение экземпляров ведет себя иначе, чем сравнение примитивов. Что, вероятно, добавляет к этой путанице. Вы увидите похожее поведение сравнения, если будете использовать версию экземпляра примитивных типов данных. Например, new String('asdf')или new Number(5). Пример: new Number(5) == new Number(5)ложь, хотя они имеют одинаковое значение.
Норман
1
Мы все забываем, что ссылка на объект на самом деле является типом значения, так как это указатель на слот памяти. Сравнение объектов не сравнивает «значение объекта», но является ли оба указателя одинаковыми, что означает, что они ссылаются на один и тот же слот памяти. Это очень тонкое различие в сравнении типов, так как оператор «===» действительно должен сказать «если тип, значение и ссылка на объект в памяти совпадают».
Стокли
101

Я проверил это в Firefox с Firebug, используя такой код:

console.time("testEquality");
var n = 0;
while(true) {
    n++;
    if(n==100000) 
        break;
}
console.timeEnd("testEquality");

а также

console.time("testTypeEquality");
var n = 0;
while(true) {
    n++;
    if(n===100000) 
        break;
}
console.timeEnd("testTypeEquality");

Мои результаты (проверены пять раз каждый и усреднены):

==: 115.2
===: 114.4

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

Саймон Скарф
источник
3
Больше, чем безопасность типов, вам нужна логическая корректность - иногда вы хотите, чтобы все было правдиво, когда вы ==не согласны.
rpjohnst
4
Теперь, как они сравниваются, когда есть фактическое приведение типа для ==оператора? Помните, что тогда происходит повышение производительности.
Юбер О.Г.
2
ОСНОВНАЯ разница при правильном тестировании по вышеупомянутым причинам быстрее проверяет только неравенство типов. jsfiddle.net/4jhuxkb2
Даг Морроу,
Вы измеряете производительность чего-то подобного в операциях в секунду, а не в одном тесте в одном браузере (один с долей рынка около 5%) с помощью console.time () при использовании теста, который не принимает приведение типа (вся причина это медленнее) во внимание. Это абсолютно бессмысленный тест. Вы правы в том, что производительность не является причиной для ===чрезмерного использования, ==но вы ошибаетесь, что их производительность практически одинакова, и вы думаете, что этот тест доказывает, что, как и многие другие люди согласились, для меня это абсолютно абсурдно.
Стивен М Ирвинг
97

В JavaScript это означает то же значение и тип.

Например,

4 == "4" // will return true

но

4 === "4" // will return false 
Димитар
источник
87

=== Оператор называется строгим оператор сравнения, он действительно отличается от == оператора.

Давайте возьмем 2 переменные a и b.

Чтобы "a == b" было оценено как истинное, a и b должны быть одинаковыми .

В случае «a === b» a и b должны иметь одинаковое значение, а также один и тот же тип, чтобы оно имело значение true.

Возьмите следующий пример

var a = 1;
var b = "1";

if (a == b) //evaluates to true as a and b are both 1
{
    alert("a == b");
}

if (a === b) //evaluates to false as a is not the same type as b
{
    alert("a === b");
}

В итоге ; использование оператора == может дать значение true в ситуациях, когда вы этого не хотите, поэтому использование оператора === будет безопаснее.

В сценарии использования 90% не имеет значения, какой из них вы используете, но удобно знать разницу, когда вы однажды получите неожиданное поведение.

Доктор джонс
источник
82

Почему == это так непредсказуемо?

Что вы получаете, когда сравниваете пустую строку ""с нулевым числом 0?

true

Да, это верно в соответствии с == пустой строкой и нулевым числом одновременно.

И это не заканчивается, вот еще один:

'0' == false // true

Вещи становятся действительно странными с массивами.

[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true

Тогда страннее со строками

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

Становится хуже:

Когда равен не равен?

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

Позвольте мне сказать это еще раз:

(A == B) && (B == C) // true
(A == C) // **FALSE**

И это просто сумасшедшие вещи, которые вы получаете с примитивами.

Это совершенно новый уровень безумия, когда вы используете ==объекты.

На данный момент ваш, вероятно, интересно ...

Почему это происходит?

Ну, это потому, что в отличие от «тройного равенства» ( ===), который просто проверяет, совпадают ли два значения.

==делает целую кучу других вещей .

Он имеет специальную обработку для функций, специальную обработку для нулей, неопределенных, строк, вы называете это.

Это довольно странно.

На самом деле, если вы попытаетесь написать функцию, которая делает то, что ==делает, она будет выглядеть примерно так:

function isEqual(x, y) { // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") {
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") {
            return x === y.toString();
        } else if(typeof y === "string") {
            return x.toString() === y;
        } 
        return false;
    }

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

Так что это значит?

Это значит == это сложно.

Поскольку это сложно, трудно понять, что произойдет, когда вы его используете.

Что означает, что вы можете получить ошибки.

Так что мораль этой истории ...

Сделай свою жизнь менее сложной.

Используйте ===вместо ==.

Конец.

Луис Перес
источник
Вы looseEqualне правы. Function == Function.toString()верно, но looseEqual(Function, Function.toString())ложно. Не уверен, почему вы отфильтровываете функции в начале.
Oriol
@ Orol, вы были правы, я обновил код, чтобы учесть это, к вашему сведению, на основании моих тестов было недостаточно убрать фильтр для «функций», вместо этого «функции» должны были обрабатываться совсем по-другому.
Луис Перес
Имейте в виду, что спецификация не обрабатывает функции по-разному, это просто объекты. Кажется, проблема в том, что вы typeof x === "object"проверяете, является ли это объектом, но `typeof работает только для ненулевых примитивов. Возможно, вас заинтересует мой список правильных способов проверить, является ли значение объектом
Oriol
Я пытался обрабатывать функции и объекты одинаково, но обнаружил, что результаты неверны. Например, если функции обрабатываются как объекты, то сравнение функции с объектом, который реализует функцию valueOf () или toString (), которая соответствует функции, пройдет, но в действительности это не так. Пример: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- проверьте этот JS Fiddle, который запускает все тесты: jsfiddle.net/luisperezphd/7k6gcn6g (там 1225 тестовых перестановок)
Луис Перес
1
Вы правы, большие наблюдения, это подчеркивает главное, что == делает многое, что делает очень трудным предвидеть результаты, в то время как ===он намного более прост и предсказуем, что является одной из основных причин ===, по которой рекомендуется делать выбор. (Я добавлю примечание к ответу, упомянув вашу точку зрения)
Луис Перес
81

===проверяет одинаковые стороны как по типу, так и по значению .


Пример:

'1' === 1 // will return "false" because `string` is not a `number`

Общий пример:

0 == ''  // will be "true", but it's very common to want this check to be "false"

Еще один распространенный пример:

null == undefined // returns "true", but in most cases a distinction is necessary

Много раз нетипизированная проверки будет удобно , потому что вы не заботитесь , если значение либо undefined, null, 0 или""

VSync
источник
7
также,'string' !== 'number'
Гомер
72

Блок-схема выполнения Javascript для строгого равенства / Сравнение '==='

Javascript строгое равенство

Блок-схема выполнения Javascript для нестрогого равенства / сравнения '=='

Javascript не равенство

Самар Панда
источник
Я не понимаю, почему stringстрелка указывает на большую серую коробку, это должно означать, что прерыватель бросает строку в число?
vsync
@vsync Указывает на параметр строки внутри серого поля, т. е. строка -> # || NaN. Javascript не является языком сценариев типов, то есть в основном он может иметь любой тип переменной. Итак, он указывает на эту серую коробку.
Самар Панда
Я просто спросил, предназначен ли он для приведения типов, поскольку stringпредполагается, что его следует сравнивать с типом number, так что прерыватель смотрит на то, с чем должна сравниваться строка, и соответственно отбрасывает ее?
vsync
1
Большой серый прямоугольник - это то, что ToNumberбудет возвращаться, если ему даны разные типы, поэтому, если ему дана строка, он выберет только последний вариант (и преобразует его в число). ==используется ToNumberтолько в случаях string == numberили boolean == anythingвыше (и только на string/ boolean). Это означает, ==что никогда не будет конвертировать undefinedили nullдаже если они находятся в сером поле. (Для любой комбинации одного undefinedили nullобоих оба ==всегда будут возвращаться true. Кроме того, не имеет значения, находится ли значение слева или справа, =====) будет возвращать тот же результат.)
user2033427
55

JavaScript === против == .

0==false   // true
0===false  // false, because they are of a different type
1=="1"     // true, auto type coercion
1==="1"    // false, because they are of a different type
Аник Ислам Абхи
источник
54

Это означает равенство без приведения типов Приведение типов означает, что JavaScript не преобразует автоматически любые другие типы данных в строковые типы данных.

0==false   // true,although they are different types

0===false  // false,as they are different types

2=='2'    //true,different types,one is string and another is integer but 
            javaScript convert 2 to string by using == operator 

2==='2'  //false because by using === operator ,javaScript do not convert 
           integer to string 

2===2   //true because both have same value and same types 
Поп-каталин
источник
48

В типичном скрипте не будет разницы в производительности. Более важным может быть тот факт, что тысяча "===" на 1 КБ тяжелее тысячи "==" :) Профилировщики JavaScript могут сказать вам, есть ли разница в производительности в вашем случае.

Но лично я бы сделал то, что предлагает JSLint. Эта рекомендация существует не из-за проблем с производительностью, а из-за того, что приведение типов означает « ('\t\r\n' == 0)истина».

Constantin
источник
4
Не всегда правда. При сжатии gzip разница будет практически незначительной.
Даниэль Х Мур
1
Согласитесь, но тысяча "===" означает еще и 10 тысяч строк кода, так что больше или меньше на 1 килобайт ...;)
Джонни
Если вы беспокоитесь о размере, просто поменяйте местами все == с ===, а затем используйте регулярное выражение, обернутое в av eval, чтобы переключить его обратно
46

Оператор сравнения == сбивает с толку и его следует избегать.

Если вы должны жить с этим, то помните следующие 3 вещи:

  1. Это не транзитивно: (a == b) и (b == c) не приводит к (a == c)
  2. Он взаимоисключающий с отрицанием: (a == b) и (a! = B) всегда содержат противоположные логические значения со всеми a и b.
  3. В случае сомнений выучите наизусть следующую таблицу истинности:

РАВНАЯ ТАБЛИЦА РАВНЫХ ОПЕРАТОРОВ В JAVASCRIPT

  • Каждая строка в таблице представляет собой набор из 3 взаимно «равных» значений, что означает, что любые 2 значения из них равны, используя знак равенства == *

** СТРАННЫЙ: обратите внимание, что любые два значения в первом столбце не равны в этом смысле. **

''       == 0 == false   // Any two values among these 3 ones are equal with the == operator
'0'      == 0 == false   // Also a set of 3 equal values, note that only 0 and false are repeated
'\t'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

null == undefined  // These two "default" values are not-equal to any of the listed values above
NaN                // NaN is not equal to any thing, even to itself.
CuongHuyTo
источник
39

Вряд ли будет какая-либо разница в производительности между двумя операциями при вашем использовании. Преобразование типов не требуется, поскольку оба параметра уже одного типа. Обе операции будут иметь сравнение типов с последующим сравнением значений.

Шон
источник
38

Да! Это имеет значение.

===Оператор в javascript проверяет значение, а также тип, где ==оператор as просто проверяет значение (выполняет преобразование типа, если требуется) .

введите описание изображения здесь

Вы можете легко проверить это. Вставьте следующий код в файл HTML и откройте его в браузере

<script>

function onPageLoad()
{
    var x = "5";
    var y = 5;
    alert(x === 5);
};

</script>

</head>

<body onload='onPageLoad();'>

Вы получите « ложь » в тревоге. Теперь измените onPageLoad()метод, чтобы alert(x == 5);вы получили истинное значение .

Аникет Тхакур
источник
33

=== Оператор проверяет значения, а также типы переменных на равенство.

== Оператор просто проверяет значение переменных на равенство.

Нираж чуби
источник
32

Это строгий проверочный тест.

Это хорошо, особенно если вы проверяете между 0 и false и null.

Например, если у вас есть:

$a = 0;

Затем:

$a==0; 
$a==NULL;
$a==false;

Все возвращает истину, и вы можете не хотеть этого. Предположим, у вас есть функция, которая может возвращать 0-й индекс массива или false при сбое. Если вы проверите «==» false, вы можете получить запутанный результат.

Так что с тем же, что и выше, но строгим тестом:

$a = 0;

$a===0; // returns true
$a===NULL; // returns false
$a===false; // returns false
Даниил
источник
3
В JavaScript это совершенно неправильно и ошибочно неполно. 0 != null, -1
Ry-
31

JSLint иногда дает вам нереальные причины для изменения материала. ===имеет точно такую ​​же производительность, как== если бы типы уже были одинаковыми.

Это быстрее, только когда типы не совпадают, и в этом случае он не пытается конвертировать типы, но напрямую возвращает false.

Итак, IMHO, JSLint может использоваться для написания нового кода, но бесполезной чрезмерной оптимизации следует избегать любой ценой.

Это означает, что нет смысла переходить ==к ===проверке, например, if (a == 'test')когда вы знаете, что факт может быть только строкой.

Таким образом, изменение большого количества кода тратит время разработчиков и рецензентов и ничего не дает.

пепел
источник
30

Просто

==означает сравнение между операндами с type conversion

&

===означает сравнение между операндами без type conversion

Преобразование типов в javaScript означает, что javaScript автоматически преобразует любые другие типы данных в строковые типы данных.

Например:

123=='123'   //will return true, because JS convert integer 123 to string '123'
             //as we used '==' operator 

123==='123' //will return false, because JS do not convert integer 123 to string 
            //'123' as we used '===' operator 
Amit
источник
26

Простой пример

2 == '2'  -> true, values are SAME because of type conversion.

2 === '2'  -> false, values are NOT SAME because of no type conversion.
Викас
источник
25

Первые два ответа оба упомянутых == означает равенство и === означает идентичность. К сожалению, это утверждение неверно.

Если оба операнда == являются объектами, то они сравниваются, чтобы увидеть, являются ли они одним и тем же объектом. Если оба операнда указывают на один и тот же объект, оператор равенства возвращает true. В противном случае два не равны.

var a = [1, 2, 3];  
var b = [1, 2, 3];  
console.log(a == b)  // false  
console.log(a === b) // false  

В приведенном выше коде оба == и === становятся ложными, потому что a и b не являются одинаковыми объектами.

То есть: если оба операнда == являются объектами, == ведет себя так же, как ===, что также означает идентичность. Существенное отличие этих двух операторов заключается в преобразовании типов. == имеет преобразование, прежде чем проверяет равенство, но === нет.

Гарри он
источник
24

Как правило, я бы обычно использовал ===вместо ==!==вместо!= ).

Причины объяснены в ответах выше, и Дуглас Крокфорд довольно ясно об этом ( JavaScript: Хорошие части ).

Однако есть одно единственное исключение : == nullэто эффективный способ проверить, является ли он пустым или неопределенным:

if( value == null ){
    // value is either null or undefined
}

Например, jQuery 1.9.1 использует этот шаблон 43 раза, и по этой причине средство проверки синтаксиса JSHint даже предоставляет возможность eqnullрасслабления.

Из руководства по стилю jQuery :

Строгие проверки на равенство (===) должны использоваться в пользу ==. Единственное исключение - при проверке неопределенности и нуля посредством нуля.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;
Mar10
источник
22

Проблема в том, что вы можете легко попасть в беду, так как JavaScript имеет много неявных преобразований, означающих ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Что довольно скоро становится проблемой. Лучший пример того, почему неявное преобразование является «злым», можно взять из этого кода в MFC / C ++, который на самом деле будет компилироваться из-за неявного преобразования из CString в HANDLE, который является указателем typedef типа ...

CString x;
delete x;

Который, очевидно, во время выполнения делает очень неопределенные вещи ...

Google для неявных преобразований в C ++ и STL, чтобы получить некоторые аргументы против этого ...

Томас Хансен
источник
2
0 == nullложно
Гарретт
21

Сравнение равенства:

оператор ==

Возвращает true, когда оба операнда равны. Операнды преобразуются в один и тот же тип перед сравнением.

>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true

Сравнение равенства и типов:

оператор ===

Возвращает true, если оба операнда имеют одинаковый тип. Как правило, это лучше и безопаснее, если сравнивать таким образом, потому что нет закулисных преобразований типов.

>>> 1 === '1'
false
>>> 1 === 1
true
user2601995
источник
20

Вот удобная таблица сравнения, которая показывает, какие преобразования происходят, и различия между ==и ===.

В заключении говорится:

«Используйте три равных, если вы не полностью понимаете преобразования, которые имеют место для двух равных».

http://dorey.github.io/JavaScript-Equality-Table/

Кристиан Хагелид
источник
20

null и undefined - это ничто, то есть

var a;
var b = null;

Здесь aи bнет ценностей. Принимая во внимание, что 0, false и '' являются значениями. Общим для всех них является то, что все они являются ложными значениями, что означает, что все они удовлетворяют ложным условиям.

Итак, 0, false и '' вместе образуют подгруппу. И с другой стороны, null & undefined образуют вторую подгруппу. Проверьте сравнения на изображении ниже. null и undefined будут равны. Три других были бы равны друг другу. Но все они рассматриваются как ложные условия в JavaScript.

Введите описание изображения здесь

Это то же самое, что и любой объект (например, {}, массивы и т. Д.), Непустая строка и логическое значение true - все условия истинности. Но они все не равны.

vivek_nk
источник