Para complementar a resposta de Wayne e tentar explicar por que ToPrimitive([])retorna "", vale a pena considerar dois tipos possíveis de respostas para a pergunta 'por que'. O primeiro tipo de resposta é: "porque a especificação diz que é assim que o JavaScript se comportará". Na especificação do ES5, seção 9.1 , que descreve o resultado de ToPrimitive como um valor padrão para um Objeto:
O valor padrão de um objeto é recuperado chamando o método interno [[DefaultValue]] do objeto, passando a dica opcional PreferredType.
Seção 8.12.8 descreve o [[DefaultValue]]método. Esse método usa uma "dica" como argumento e a dica pode ser String ou Number. Para simplificar o assunto dispensando alguns detalhes, se a dica for String, [[DefaultValue]]retornará o valor de toString()se ele existir e retornará um valor primitivo e, caso contrário, retornará o valor de valueOf(). Se a dica for Number, as prioridades de toString()e valueOf()serão revertidas para que valueOf()seja chamado primeiro e seu valor retornado se for um primitivo. Portanto, se [[DefaultValue]]retorna o resultado toString()ou valueOf()depende do PreferredType especificado para o objeto e se essas funções retornam ou não valores primitivos.
O valueOf()método Object padrão apenas retorna o próprio objeto, o que significa que, a menos que uma classe substitua o método padrão, valueOf()apenas retorna o próprio objeto. Este é o caso Array. [].valueOf()retorna o []próprio objeto . Como um Arrayobjeto não é primitivo, a [[DefaultValue]]dica é irrelevante: o valor de retorno para uma matriz será o valor de toString().
Para citar o JavaScript de David Flanagan : The Definitive Guide , que, a propósito, é um livro excelente que deve ser o primeiro lugar de todos para obter respostas para esses tipos de perguntas:
Os detalhes dessa conversão de objeto em número explicam por que uma matriz vazia se converte no número 0 e por que uma matriz com um único elemento também pode ser convertida em um número. As matrizes herdam o método valueOf () padrão que retorna um objeto em vez de um valor primitivo, portanto, a conversão de matriz em número depende do método toString (). Matrizes vazias são convertidas para a sequência vazia. E a sequência vazia é convertida no número 0. Uma matriz com um único elemento é convertida na mesma sequência que esse elemento. Se uma matriz contiver um único número, esse número será convertido em uma sequência e, em seguida, voltará a um número.
O segundo tipo de resposta para a pergunta "por que", exceto "porque a especificação diz", fornece algumas explicações sobre por que o comportamento faz sentido da perspectiva do design. Sobre esta questão, só posso especular. Primeiro, como converter uma matriz em um número? A única possibilidade sensata que consigo pensar seria converter uma matriz vazia em 0 e qualquer matriz não vazia em 1. Mas, como a resposta de Wayne revelou, uma matriz vazia será convertida em 0 para muitos tipos de comparações de qualquer maneira. Além disso, é difícil pensar em um valor de retorno primitivo sensível para Array.valueOf (). Portanto, pode-se argumentar que faz mais sentido ter Array.valueOf()o padrão e retornar a própria matriz, levando toString()ao resultado usado pelo ToPrimitive. Faz mais sentido converter uma matriz em uma cadeia de caracteres do que em um número.
Além disso, como sugerido pela citação de Flanagan, essa decisão de design permite certos tipos de comportamentos benéficos. Por exemplo:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
Esse comportamento permite comparar uma matriz de elemento único com números e obter o resultado esperado.