Para complementar la respuesta de Wayne y tratar de explicar por qué ToPrimitive([])
regresa ""
, vale la pena considerar dos posibles tipos de respuestas a la pregunta 'por qué'. El primer tipo de respuesta es: "porque la especificación dice que así es como se comportará JavaScript". En la especificación ES5, sección 9.1 , que describe el resultado de ToPrimitive como valor predeterminado para un objeto:
El valor predeterminado de un objeto se recupera llamando al método interno [[DefaultValue]] del objeto, pasando la sugerencia opcional PreferredType.
La Sección 8.12.8 describe el [[DefaultValue]]
método. Este método toma una "pista" como argumento, y la pista puede ser String o Number. Para simplificar el asunto prescindiendo de algunos detalles, si la pista es String, [[DefaultValue]]
devuelve el valor de toString()
si existe y devuelve un valor primitivo y, de lo contrario, devuelve el valor de valueOf()
. Si la sugerencia es Número, las prioridades de toString()
y valueOf()
se invierten, por lo que valueOf()
se llama primero y se devuelve su valor si es un primitivo. Por lo tanto, si [[DefaultValue]]
devuelve el resultado toString()
o valueOf()
depende del PreferredType especificado para el objeto y si estas funciones devuelven o no valores primitivos.
El valueOf()
método Object predeterminado solo devuelve el objeto en sí, lo que significa que a menos que una clase anule el método predeterminado, valueOf()
solo devuelve el Object en sí. Este es el caso para Array
. [].valueOf()
devuelve el objeto en []
sí. Como un Array
objeto no es primitivo, la [[DefaultValue]]
sugerencia es irrelevante: el valor de retorno para una matriz será el valor de toString()
.
Para citar el JavaScript de David Flanagan : The Definitive Guide , que, por cierto, es un libro excelente que debería ser el primer lugar de todos para obtener respuestas a este tipo de preguntas:
Los detalles de esta conversión de objeto a número explican por qué una matriz vacía se convierte en el número 0 y por qué una matriz con un solo elemento también puede convertirse en un número. Las matrices heredan el método predeterminado valueOf () que devuelve un objeto en lugar de un valor primitivo, por lo que la conversión de matriz a número se basa en el método toString (). Las matrices vacías se convierten en la cadena vacía. Y la cadena vacía se convierte en el número 0. Una matriz con un solo elemento se convierte en la misma cadena que ese elemento. Si una matriz contiene un solo número, ese número se convierte en una cadena y luego vuelve a un número.
El segundo tipo de respuesta a la pregunta "por qué", que no sea "porque la especificación dice", da una explicación de por qué el comportamiento tiene sentido desde la perspectiva del diseño. Sobre este tema solo puedo especular. Primero, ¿cómo se convertiría una matriz en un número? La única posibilidad sensata que se me ocurre sería convertir una matriz vacía a 0 y cualquier matriz no vacía a 1. Pero como reveló la respuesta de Wayne, una matriz vacía se convertirá a 0 para muchos tipos de comparaciones de todos modos. Más allá de esto, es difícil pensar en un valor de retorno primitivo sensible para Array.valueOf (). Por lo tanto, se podría argumentar que tiene más sentido tener Array.valueOf()
el valor predeterminado y devolver la matriz en sí, lo toString()
que lleva a ser el resultado utilizado por ToPrimitive. Simplemente tiene más sentido convertir una matriz en una cadena, en lugar de un número.
Además, como lo sugiere la cita de Flanagan, esta decisión de diseño permite ciertos tipos de comportamientos beneficiosos. Por ejemplo:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
Este comportamiento le permite comparar una matriz de un solo elemento con números y obtener el resultado esperado.