Me había preocupado por esto durante mucho tiempo, así que finalmente investigué esto y le di esta razón larga y sin aliento de por qué las cosas son como son.
De la especificación :
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)
Así que ahora vamos a 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.
Eso es. El operador triple igual aplicado a las cadenas devuelve verdadero si los argumentos son exactamente las mismas cadenas (la misma longitud y los mismos caracteres en las posiciones correspondientes).
Por ===
lo tanto , funcionará en los casos en que intentemos comparar cadenas que podrían haber llegado de diferentes fuentes, pero que sabemos que eventualmente tendrán los mismos valores, un escenario lo suficientemente común para cadenas en línea en nuestro código. Por ejemplo, si tenemos una variable llamada connection_state
y deseamos saber en cuál de los siguientes estados se ['connecting', 'connected', 'disconnecting', 'disconnected']
encuentra en este momento, podemos usar directamente ===
.
Pero hay más. Justo arriba de 11.9.4, hay una 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 ¿Ahora que? Las cadenas obtenidas externamente pueden, y muy probablemente serán, unicodey extrañas, y nuestro gentil ===
no les hará justicia. En viene localeCompare
al rescate:
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 irnos a casa ahora.
tl; dr;
Para comparar cadenas en javascript, use localeCompare
; si sabe que las cadenas no tienen componentes que no sean ASCII porque son, por ejemplo, constantes internas del programa, entonces ===
también funcionan.
JavaScript case insensitive string comparison
en stackoverflow.com/questions/2140627/…