En lugar de repetir el resultado que demostró en la pregunta, intentaré dar una descripción de por qué obtiene ese resultado.
Explicación
Tomando sólo el primer ejemplo (porque el resto va a hacer algo similar), podemos seguir la especificación para ver qué pasa.
De 11.4.6 Unary + Operator, podemos ver que se lleva a cabo una conversión de ToNumber
.
Return ToNumber (GetValue (expr)).
De 9.3 ToNumber vemos que si se les da un objeto (como Array), una conversión ToPrimitive
tiene lugar seguido de otro intento de ToNumber
.
objeto
Aplicar los siguientes pasos:
- Vamos primValue ser ToPrimitive (argumento de entrada, Número de pista).
- Volver aNúmero (primValue).
De 9.1 To Primitive, si ToPrimitive
Obtiene un objeto, podemos ver que su [[DefaultValue]]
es inverosímil:
objeto
devolver un valor predeterminado para el objeto. El valor predeterminado de un objeto se recupera llamando al método interno [[DefaultValue]] del objeto, pasando la sugerencia opcional PreferredType. El comportamiento del método interno [[DefaultValue]] está definido por esta especificación para todos los objetos ECMAScript nativos en 8.12.8.
De 8.12.8 [[DefaultValue]] (hint), lo que finalmente suceda será que toString()
serán llamados en la matriz, y regresaron. Esta cadena se envía al recursivo ToNumber
como se describe arriba.
Entonces, ¿qué ocurre cuando la conversión ToNumber
se realiza en una cadena? Bueno, se describe en 9.3.1 ToNumber Applied to the String Type, y es un poco largo. Más simple es simplemente hacer la conversión directa, y ver lo que sucede:
Number(""); // result is 0 on an empty string
Number(" "); // result is 0 on a string with only whitespace
Number("123"); // result is 123 on a numeric string
Number(" 123 ");// result is 123 on a numeric string with leading & trailing spaces
Number("abc"); // result is NaN (not a number) on non-numeric strings
Entonces la pregunta es, ¿qué hacer cadena volvamos de nuestra matriz. De nuevo, esto es fácil de simplemente probar.
[].toString(); // result is "" (empty string)
Como el resultado es una cadena vacía, y una conversión ToNumber
de una cadena vacía es 0
como se muestra arriba, que significaría estamos comparando 0 === 0
.
Sería lo mismo que si lo hicimos:
Number([].toString()) === 0; // true
O a lo alcanzará un poco más:
var x = [];
x = x.toString(); // ""
x = Number(x); // 0
x === 0; // true
Más toString
resultados.
para mostrar más toString
conversiones de matrices, tenga en cuenta lo siguiente:
[1].toString(); // "1"
[1,2,3].toString(); // "1,2,3"
["a",1,"b",2].toString(); // "a,1,b,2"
Así que para hacer una conversión ToNumber
en las matrices anteriores, la primera sería darnos un número, y las dos últimas se traduciría en NaN
.
Number([1]); // 1
Number([1,2,3]); // NaN
Number(["a",1,"b",2]); // NaN
alguna prueba
Para proporcionar una prueba más de que esta conversión toString()
ocurre antes de la conversión ToNumber
, en realidad podemos modificar Array.prototype.toString
para proporcionar un resultado diferente, y cualquier ToNumber
conversiones utilizaremos dicha resultado modificado.
Array.prototype.toString = function() {
var n = 0;
for(var i = 0; i < this.length; i++) {
n += this[i];
}
return n;
};
Aquí he reemplazado el toString
en Array.prototype
con una función que resume la matriz. Obviamente, no quiere hacer esto, pero podemos mostrar cómo obtendremos un resultado diferente.
Number([1,2,3]); // 6
+[1,2,3]; // 6
Así que ahora se puede ver que la conversión ToNumber
de nuestra matriz que anteriormente habrían dado lugar a NaN
está dando lugar a la suma de los elementos de la matriz.
Creo que me gustaría voltear el escritorio si me encontré con un código como ese. –
la respuesta es: '+ [NaN] == !!!! 0 && + [{}] + ~~ [[]] - []' – jAndy
Si vi eso en cualquier código, le pediría al desarrollador original que reescriba eso. ¡Es una muy mala práctica! –