Eu me preocupei com isso por muito tempo, então finalmente pesquisei sobre isso e explico por que as coisas são do jeito que são.
Das especificações :
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)
Então agora vamos para 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.
É isso aí. O operador triple equals aplicado às strings retorna true se os argumentos são exatamente as mesmas strings (mesmo comprimento e mesmos caracteres nas posições correspondentes).
Portanto ===
, funcionará nos casos em que estivermos tentando comparar cadeias que podem ter chegado de fontes diferentes, mas que sabemos que acabarão tendo os mesmos valores - um cenário bastante comum para cadeias de caracteres embutidas em nosso código. Por exemplo, se tivermos uma variável denominada connection_state
e desejamos saber em qual dos seguintes estados ['connecting', 'connected', 'disconnecting', 'disconnected']
ela está agora, podemos usar diretamente o ===
.
Mas tem mais. Logo acima do 11.9.4, há uma breve nota:
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. E agora? Cordas obtidas externamente podem, e muito provavelmente serão, unicodey estranho, e nosso gentil ===
não fará justiça a elas. Em vem localeCompare
ao salvamento:
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.
Podemos ir para casa agora.
tl; dr;
Para comparar strings em javascript, use localeCompare
; se você souber que as seqüências não têm componentes não ASCII porque são, por exemplo, constantes internas do programa, ===
também funciona.
JavaScript case insensitive string comparison
em stackoverflow.com/questions/2140627/…