Martwiłem się tym przez długi czas, więc w końcu to zbadałem i podałem ci ten długi powód, dlaczego rzeczy są takie, jakie są.
Ze specyfikacji :
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)
Teraz przechodzimy do 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.
Otóż to. Potrójny operator równości zastosowany do ciągów zwraca true, jeśli argumenty są dokładnie tymi samymi ciągami (ta sama długość i te same znaki w odpowiednich pozycjach).
Tak więc ===
będzie działać w przypadkach, gdy próbujemy porównać ciągi, które mogły przybyć z różnych źródeł, ale które, jak wiemy, ostatecznie będą miały te same wartości - dość powszechny scenariusz dla wbudowanych ciągów w naszym kodzie. Na przykład, jeśli mamy zmienną o nazwie connection_state
, i chcemy wiedzieć, który z poniższych stanów ['connecting', 'connected', 'disconnecting', 'disconnected']
jest w tej chwili, możemy bezpośrednio użyć ===
.
Ale jest coś więcej. Tuż powyżej wersji 11.9.4 jest krótka notatka:
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.
Hmm Co teraz? Zewnętrznie uzyskane struny mogą i najprawdopodobniej będą dziwnym jednorożcem, a nasi delikatni ===
nie oddadzą im sprawiedliwości. Przychodzi localeCompare
na ratunek:
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.
Możemy już iść do domu.
tl; dr;
Aby porównać ciągi w javascript, użyj localeCompare
; jeśli wiesz, że ciągi nie zawierają żadnych elementów spoza ASCII, ponieważ są one na przykład wewnętrznymi stałymi programu, to ===
również działa.
JavaScript case insensitive string comparison
na stackoverflow.com/questions/2140627/…