Какой оператор равенства (== vs ===) следует использовать в сравнениях JavaScript?
Я использую JSLint, чтобы пройти через JavaScript, и он возвращает много предложений, чтобы заменить ==
(два знака равенства) с ===
(три знака равенства) при выполнении таких вещей, как сравнение idSele_UNVEHtype.value.length == 0
внутри if
заявление.
Есть ли выигрыш в производительности для замены ==
с ===
?
Любое улучшение производительности будет приветствоваться, так как существует много операторов сравнения.
Если преобразование типов не выполняется, будет ли увеличение производительности по сравнению с ==
?
49 ответов
Личность (===
) оператор ведет себя идентично равенству (==
), за исключением того, что преобразование типов не выполняется, и типы должны быть одинаковыми, чтобы считаться равными.
Ссылка: Учебник по 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 в комментариях и в Philippe Leybaert относительно ссылочных типов. Для справочных типов ==
а также ===
действовать последовательно друг с другом (кроме как в особом случае).
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
конструктор для создания строковых объектов.
С использованием ==
оператор (равенство)
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
Это потому, что оператор равенства ==
выполняет приведение типов, что означает, что интерпретатор неявно пытается преобразовать значения перед сравнением.
С другой стороны, тождественный оператор ===
не выполняет приведение типов и, следовательно, не преобразует значения при сравнении.
Интересное наглядное представление сравнения равенства ==
а также ===
,
Источник: http://dorey.github.io/JavaScript-Equality-Table/
var1 === var2
Когда используешь
===
для проверки на равенство JavaScript все как есть. Ничто не преобразуется перед оценкой.
var1 == var2
Когда используешь
==
для проверки на равенство JavaScript выполняются некоторые интересные преобразования.
Мораль истории:
использование
===
если вы не полностью понимаете преобразования, которые происходят с==
,
В ответах здесь я ничего не читал о том, что значит равный. Некоторые скажут, что ===
означает равный и того же типа, но это не совсем так. Фактически это означает, что оба операнда ссылаются на один и тот же объект или, в случае типов значений, имеют одинаковое значение.
Итак, давайте возьмем следующий код:
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
который ведет себя как строка большую часть времени.
Позвольте мне добавить этот совет:
Если сомневаетесь, прочитайте спецификацию!
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. Верните true, если x и y ссылаются на один и тот же объект или если они ссылаются на объекты, соединенные друг с другом (см. 13.1.2). В противном случае верните false.
Интересным является шаг 11. Да, строки обрабатываются как типы значений. Но это не объясняет, почему новая String ("a")!== "a". У нас есть браузер, не соответствующий ECMA-262?
Не так быстро!
Давайте проверим типы операндов. Попробуйте сами, обернув их в typeof (). Я обнаружил, что новая строка ("a") является объектом, и используется шаг 1: вернуть false, если типы различаются.
Если вам интересно, почему new String("a") не возвращает строку, как насчет упражнения по чтению спецификации? Повеселись!
Aidiakapi написал это в комментарии ниже:
Из спецификации
11.2.2 Новый Оператор:
Если Type (конструктор) не является Object, генерировать исключение TypeError.
Другими словами, если бы String не был типа Object, его нельзя было бы использовать с оператором new.
new всегда возвращает Object, даже для конструкторов String. И увы! Семантика значения для строк (см. Шаг 11) потеряна.
И это, наконец, означает: новая строка ("а")!== "а".
Я проверил это в 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), и качество кода.
В PHP и JavaScript это оператор строгого равенства. Это означает, что он будет сравнивать как тип, так и значения.
В JavaScript это означает одно и то же значение и тип.
Например,
4 == "4" // will return true
но
4 === "4" // will return false
Зачем ==
так непредсказуемо?
Что вы получаете, когда вы сравниваете пустую строку ""
с нулевым числом 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();
}
Так что это значит?
Это значит ==
это сложно.
Поскольку это сложно, трудно понять, что произойдет, когда вы его используете.
Это означает, что вы можете получить ошибки.
Так что мораль этой истории...
Сделай свою жизнь менее сложной.
использование ===
вместо ==
,
Конец.
Оператор === называется оператором строгого сравнения, он отличается от оператора ==.
Давайте возьмем 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% не имеет значения, какой из них вы используете, но удобно знать разницу, когда однажды вы получаете неожиданное поведение.
Он проверяет, равны ли одинаковые стороны по типу и значению.
Пример:
'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
Блок-схема выполнения Javascript для строгого равенства / Сравнение '==='
Блок-схема выполнения Javascript для нестрогого равенства / сравнения '=='
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
Это означает равенство без приведения типов Приведение типов означает, что 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
В типичном скрипте не будет разницы в производительности. Более важным может быть тот факт, что тысяча "===" на 1 КБ тяжелее тысячи "==":) Профилировщики JavaScript могут подсказать, есть ли разница в производительности в вашем случае.
Но лично я бы сделал то, что предлагает JSLint. Эта рекомендация существует не из-за проблем с производительностью, а потому, что приведение типов означает ('\t\r\n' == 0)
правда.
Оператор сравнения == сбивает с толку и его следует избегать.
Если вы должны жить с этим, то помните следующие 3 вещи:
- Это не транзитивно: (a == b) и (b == c) не приводит к (a == c)
- Он взаимоисключающий с отрицанием: (a == b) и (a!= B) всегда содержат противоположные логические значения со всеми a и b.
- В случае сомнений выучите наизусть следующую таблицу истинности:
РАВНАЯ ТАБЛИЦА РАВНЫХ ОПЕРАТОРОВ В 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.
Вряд ли будет какая-либо разница в производительности между двумя операциями при вашем использовании. Преобразование типов не требуется, поскольку оба параметра уже одного типа. Обе операции будут иметь сравнение типов с последующим сравнением значений.
Просто
==
означает сравнение между операндами с 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
Да! Это имеет значение.
===
Оператор в JavaScript проверяет значение, а также тип, где, как ==
Оператор просто проверяет значение (выполняет преобразование типа, если требуется).
Вы можете легко проверить это. Вставьте следующий код в файл HTML и откройте его в браузере
<script>
function onPageLoad()
{
var x = "5";
var y = 5;
alert(x === 5);
};
</script>
</head>
<body onload='onPageLoad();'>
Вы получите "ложь" в тревоге. Теперь измените onPageLoad()
метод для alert(x == 5);
ты станешь правдой.
Как правило, я бы вообще использовал ===
вместо ==
(а также !==
вместо !=
).
Причины объяснены в ответах выше, и Дуглас Крокфорд довольно ясно об этом ( JavaScript: Хорошие части).
Однако есть одно единственное исключение:== null
эффективный способ проверить, является ли значение null или undefined:
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;
Это строгий проверочный тест.
Это хорошо, особенно если вы проверяете между 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
===
Оператор проверяет значения, а также типы переменных на равенство.
==
Оператор просто проверяет значение переменных на равенство.
JSLint иногда дает вам нереальные причины для изменения вещей. ===
имеет точно такую же производительность, как ==
если типы уже совпадают.
Это быстрее, только когда типы не совпадают, и в этом случае он не пытается конвертировать типы, но напрямую возвращает false.
Итак, IMHO, JSLint может использоваться для написания нового кода, но бесполезной чрезмерной оптимизации следует избегать любой ценой.
Смысл, нет причин менять ==
в ===
в чеке, как if (a == 'test')
когда вы знаете, что факт может быть только строкой.
Таким образом, изменение большого количества кода тратит время разработчиков и рецензентов и ничего не дает.
Простой пример
2 == '2' -> true, values are SAME because of type conversion.
2 === '2' -> false, values are NOT SAME because of no type conversion.
В двух верхних ответах оба упомянутых == означают равенство, а === означает идентичность. К сожалению, это утверждение неверно.
Если оба операнда == являются объектами, то они сравниваются, чтобы увидеть, являются ли они одним и тем же объектом. Если оба операнда указывают на один и тот же объект, оператор равенства возвращает true. В противном случае два не равны.
var a = [1, 2, 3];
var b = [1, 2, 3];
console.log(a == b) // false
console.log(a === b) // false
В приведенном выше коде оба == и === становятся ложными, потому что a и b не являются одинаковыми объектами.
То есть: если оба операнда == являются объектами, == ведет себя так же, как ===, что также означает идентичность. Существенное отличие этих двух операторов заключается в преобразовании типов. == имеет преобразование, прежде чем проверяет равенство, но === нет.
===
Возвращаетtrue
если операнды строго равны (см. выше) без преобразования типов.
Проблема в том, что вы можете легко попасть в беду, так как JavaScript имеет много неявных преобразований, означающих...
var x = 0;
var isTrue = x == null;
var isFalse = x === null;
Что довольно скоро становится проблемой. Лучший пример того, почему неявное преобразование является "злым", можно взять из этого кода в MFC / C++, который на самом деле будет компилироваться из-за неявного преобразования из CString в HANDLE, который является указателем typedef типа...
CString x;
delete x;
Который, очевидно, во время выполнения делает очень неопределенные вещи...
Google для неявных преобразований в C++ и STL, чтобы получить некоторые аргументы против этого...
Сравнение равенства:
оператор ==
Возвращает true, когда оба операнда равны. Операнды преобразуются в один и тот же тип перед сравнением.
>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true
Равенство и сравнение типов:
оператор ===
Возвращает true, если оба операнда равны и имеют одинаковый тип. Как правило, это лучше и безопаснее, если сравнивать таким образом, потому что нет закулисных преобразований типов.
>>> 1 === '1'
false
>>> 1 === 1
true
Вот удобная таблица сравнения, которая показывает, какие конверсии происходят, и различия между ==
а также ===
,
В заключении говорится:
"Используйте три равных, если вы не полностью понимаете преобразования, которые имеют место для двух равных".
null и undefined - это ничто, то есть
var a;
var b = null;
Вот a
а также b
не имеют значения. Принимая во внимание, что 0, false и '' являются значениями. Общим для всех них является то, что все они являются ложными значениями, что означает, что все они удовлетворяют ложным условиям.
Итак, 0, false и '' вместе образуют подгруппу. И с другой стороны, null & undefined образуют вторую подгруппу. Проверьте сравнения на изображении ниже. null и undefined будут равны. Три других были бы равны друг другу. Но все они рассматриваются как ложные условия в JavaScript.
Это то же самое, что и любой объект (например, {}, массивы и т. Д.), Непустая строка и логическое значение true - все условия истинности. Но они все не равны.