Я долго беспокоился об этом, поэтому я наконец исследовал это и дал вам эту длинную причудливую причину того, почему вещи такие, какие они есть.
Из спецификации :
Section 11.9.4 The Strict Equals Operator ( === )
The production EqualityExpression : EqualityExpression === RelationalExpression
is evaluated as follows:
- Let lref be the result of evaluating EqualityExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating RelationalExpression.
- Let rval be GetValue(rref).
- Return the result of performing the strict equality comparison
rval === lval. (See 11.9.6)
Итак, теперь мы переходим к 11.9.6
11.9.6 The Strict Equality Comparison Algorithm
The comparison x === y, where x and y are values, produces true or false.
Such a comparison is performed as follows:
- If Type(x) is different from Type(y), return false.
- If Type(x) is Undefined, return true.
- If Type(x) is Null, return true.
- If Type(x) is Number, then
...
- If Type(x) is String, then return true if x and y are exactly the
same sequence of characters (same length and same characters in
corresponding positions); otherwise, return false.
Вот и все. Оператор тройного равенства, применяемый к строкам, возвращает истину, если аргументы являются абсолютно одинаковыми строками (одинаковой длины и одинаковых символов в соответствующих позициях).
То ===
же самое будет работать в тех случаях, когда мы пытаемся сравнить строки, которые, возможно, поступили из разных источников, но которые мы знаем, в конечном итоге будут иметь одинаковые значения - достаточно распространенный сценарий для встроенных строк в нашем коде. Например, если у нас есть переменная с именем connection_state
, и мы хотим знать, в каком из следующих состояний ['connecting', 'connected', 'disconnecting', 'disconnected']
она находится сейчас, мы можем напрямую использовать ===
.
Но это еще не все. Чуть выше 11.9.4, есть короткое примечание:
NOTE 4
Comparison of Strings uses a simple equality test on sequences of code
unit values. There is no attempt to use the more complex, semantically oriented
definitions of character or string equality and collating order defined in the
Unicode specification. Therefore Strings values that are canonically equal
according to the Unicode standard could test as unequal. In effect this
algorithm assumes that both Strings are already in normalized form.
Хм. Что теперь? Струны, полученные извне, могут быть, и, скорее всего, будут странными юникодами, и наши нежные ===
не сделают им должного . На localeCompare
помощь приходит :
15.5.4.9 String.prototype.localeCompare (that)
...
The actual return values are implementation-defined to permit implementers
to encode additional information in the value, but the function is required
to define a total ordering on all Strings and to return 0 when comparing
Strings that are considered canonically equivalent by the Unicode standard.
Теперь мы можем идти домой.
ТЛ; др;
Чтобы сравнить строки в JavaScript, используйте localeCompare
; если вы знаете, что в строках нет компонентов, отличных от ASCII, потому что они, например, являются внутренними программными константами, то это ===
тоже работает.
JavaScript case insensitive string comparison
на stackoverflow.com/questions/2140627/…