В Javascript <int-value> == "<int-value>" оценивается как true. Почему это так?
Если я делаю 0 == "0", это оценивается как истина. Пытаться,
if( -777 == "-777" ) alert("same");
оповещение происходит.
И также заметно, что true == "true" не оценивается как true. Пытаться,
if( false == "false" ) alert("same");
оповещение не происходит.
Почему это так?
8 ответов
Поведение == немного длинное, но четко определено в спецификации ecma-262:
11.9.3. Алгоритм сравнения абстрактного равенства
Сравнение x == y, где x и y - значения, дает истину или ложь. Такое сравнение выполняется следующим образом:
- Если Тип (x) отличается от Типа (y), перейдите к шагу 14.
- Если Тип (x) не определен, вернуть true.
- Если Type (x) равен Null, вернуть true.
- Если Тип (x) не Номер, перейдите к шагу 11.
- Если x равен NaN, вернуть false.
- Если y равен NaN, вернуть false.
- Если x - это то же числовое значение, что и y, вернуть true.
- Если x равен +0, а y равен −0, вернуть true.
- Если x равен −0, а y равен +0, верните true.
- Вернуть ложь.
- Если Type (x) - String, тогда вернуть true, если x и y - это абсолютно одинаковая последовательность символов (одинаковая длина и одинаковые символы в соответствующих позициях). В противном случае верните false.
- Если Type (x) - логическое значение, вернуть true, если x и y оба - true или оба false. В противном случае верните false.
- Верните true, если x и y ссылаются на один и тот же объект или если они ссылаются на объекты, соединенные друг с другом (см. 13.1.2). В противном случае верните false.
- Если x равно нулю, а y не определено, верните true.
- Если x не определено, а y равно нулю, верните true.
- Если Type (x) равен Number, а Type (y) равен String, вернуть результат сравнения x == ToNumber(y).
- Если Type (x) равен String, а Type (y) равен Number, вернуть результат сравнения ToNumber(x) == y.
- Если Type (x) - Boolean, вернуть результат сравнения ToNumber(x) == y.
- Если Type (y) - Boolean, вернуть результат сравнения x == ToNumber(y).
- Если Type (x) равен либо String, либо Number, а Type (y) равен Object, возвращает результат сравнения x == ToPrimitive(y).
- Если Type (x) равен Object, а Type (y) является либо String, либо Number, вернуть результат сравнения ToPrimitive(x) == y.
- Вернуть ложь.
Шаг 16 относится к вашему прежнему примеру:
0 == "0" // apply 16
≡ 0 == toNumber("0")
≡ 0 == 0 // apply 7
≡ true
И шаг 18, затем шаг 16, применяются к последнему:
true == "true" // apply 18
≡ toNumber(true) == "true"
≡ 1 == "true" // apply 16
≡ 1 == toNumber("true")
≡ 1 == NaN // apply 6
≡ false
Делая это:
if(5 == "5")
Заставляет javascript конвертировать первые 5 в строку. Попробуй это:
if(5 === "5")
===
заставляет Javascript также оценивать тип.
Это на самом деле дубликат этого question
где это объясняется очень хорошо.
Поскольку Javascript свободно напечатан, он будет автоматически приводить ваши переменные в зависимости от операции и типа других переменных в операции.
alert ("5" - 1); // 4 (int)
alert ("5" + 1); // "51" (string) "+" is a string operator, too
alert ("5" == 5); // true
То, что вы могли бы посмотреть на это проверка личности (===
). Это гарантирует, что переменные идентичны, а не просто равны.
alert("5" == 5); // true, these are equal
alert("5" === 5); // false, these are not identical.
Также посмотрите на этот вопрос: Чем отличаются операторы сравнения равенства и тождества? Реализация PHP очень похожа на реализацию JavaScript.
JavaScript имеет два набора операторов равенства:
=== and !==
(операторы строгого равенства)== and !=
(стандартные операторы равенства)
Стандартные операторы равенства будут выполнять правильное сравнение, если оба операнда имеют одинаковый тип, но вы можете получить неожиданные результаты, если они не одного типа, например:
'' == '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
Для этого я всегда рекомендую использовать операторы строгого равенства (===,!==).
Почему это так?
Потому что JavaScript является как свободно набранным, так и крайне противоречивым. Не все его конструктивные особенности хорошо продуманы; он был создан, внедрен и развернут невероятно быстро по сравнению с любым другим языком программирования, спеша выпустить Netscape 2.0. Вскоре после этого он успокоился, потерял некоторые из наиболее вопиющих ошибок и стал полу-стандартизированным.
Поиск какого-то философского обоснования таких вещей, как неявные правила приведения типов, может оказаться бесполезным занятием. Единственный действительно непротиворечивый принцип, которого придерживается JavaScript, - это DWIM, очень в отрицательном смысле.
Javascript - это слабо типизированный язык, поэтому типы типов выполняются во время выполнения всякий раз, когда интерпретатор считает, что это необходимо. Если вы сравните целое число со строкой, это показывает, что они должны быть одного типа, например, "34" == 34 - это истина, поскольку целое число, вероятно, будет приведено к типу перед строкой перед сравнением.
Строка "false" не является типизированным в bool, вместо этого ложное bool типизируется в строку, которая фактически будет иметь значение "0", то есть строку, содержащую число 0, что дает "0" == " ложно ", что, очевидно, ложно.
Если вы хотите сравнить значение без автоматической приведения типов, эффективно сравнивая типы и значения, используйте тройное равенство:
5 === "5" false "string" === "string" true
Javascript не приводит "false" к логическому false, только к строке "false".
Вы можете свободно приводить строковые значения к их целочисленному эквиваленту, таким образом, ваш первый пример работает.
JavaScript определяет значения Falsey равными 0, логические значения false и undefined. Любая строка за пределами "0" будет истинной, даже если эта строка "ложная".
Действительно раздражает.