Aby uzupełnić odpowiedź Wayne'a i spróbować wyjaśnić, dlaczego ToPrimitive([])
powraca ""
, warto rozważyć dwa możliwe typy odpowiedzi na pytanie „dlaczego”. Pierwszy typ odpowiedzi brzmi: „ponieważ specyfikacja mówi, że tak będzie działał JavaScript”. W specyfikacji ES5, sekcja 9.1 , która opisuje wynik ToPrimitive jako wartość domyślną dla obiektu:
Domyślna wartość obiektu jest pobierana poprzez wywołanie wewnętrznej metody [[DefaultValue]] obiektu, przekazując opcjonalną wskazówkę PreferredType.
Sekcja 8.12.8 opisuje tę [[DefaultValue]]
metodę. Ta metoda przyjmuje „podpowiedź” jako argument, a podpowiedź może być ciągiem lub liczbą. Aby uprościć sprawę, rezygnując z niektórych szczegółów, jeśli podpowiedź to String, to [[DefaultValue]]
zwraca wartość toString()
if, jeśli istnieje i zwraca pierwotną wartość, a w przeciwnym razie zwraca wartość valueOf()
. Jeśli wskazówką jest Liczba, priorytety toString()
i valueOf()
są odwrócone, tak więc valueOf()
wywoływana jest pierwsza, a jej wartość zwracana, jeśli jest prymitywna. Tak więc, czy [[DefaultValue]]
zwraca wynik toString()
lub valueOf()
zależy od określonego PreferredType dla obiektu i czy te funkcje zwracają wartości prymitywne.
Domyślna valueOf()
metoda Object po prostu zwraca sam obiekt, co oznacza, że jeśli klasa nie zastąpi metody domyślnej, valueOf()
po prostu zwraca sam Obiekt. Tak jest w przypadku Array
. [].valueOf()
zwraca []
sam obiekt . Ponieważ Array
obiekt nie jest prymitywny, [[DefaultValue]]
podpowiedź nie ma znaczenia: wartością zwracaną dla tablicy będzie wartość toString()
.
Cytując JavaScript Davida Flanagana : The Definitive Guide , który, nawiasem mówiąc, jest świetną książką, która powinna być pierwszym miejscem, w którym każdy powinien uzyskać odpowiedzi na tego rodzaju pytania:
Szczegóły tej konwersji obiekt-liczba wyjaśniają, dlaczego pusta tablica konwertuje na liczbę 0 i dlaczego tablica z pojedynczym elementem może również konwertować na liczbę. Tablice dziedziczą domyślną metodę valueOf (), która zwraca obiekt, a nie pierwotną wartość, więc konwersja tablic na liczby zależy od metody toString (). Puste tablice są konwertowane na pusty ciąg. A pusty łańcuch konwertuje na liczbę 0. Tablica z pojedynczym elementem konwertuje na ten sam ciąg, co ten jeden element. Jeśli tablica zawiera pojedynczy numer, liczba ta jest konwertowana na ciąg znaków, a następnie z powrotem na liczbę.
Drugi rodzaj odpowiedzi na pytanie „dlaczego”, inny niż „ponieważ specyfikacja mówi”, daje pewne wyjaśnienie, dlaczego zachowanie ma sens z punktu widzenia projektu. W tej kwestii mogę tylko spekulować. Po pierwsze, jak przekonwertować tablicę na liczbę? Jedyną sensowną możliwością, jaką mogę wymyślić, byłoby przekonwertowanie pustej tablicy na 0, a dowolnej niepustej tablicy na 1. Ale jak ujawniła odpowiedź Wayne'a, pusta tablica zostanie przekonwertowana na 0 dla wielu typów porównań. Poza tym trudno jest wymyślić sensowną prymitywną wartość zwracaną dla Array.valueOf (). Można więc argumentować, że sensowniej jest mieć Array.valueOf()
wartość domyślną i zwrócić samą tablicę, co prowadzi toString()
do wyniku używanego przez ToPrimitive. Bardziej sensowne jest przekonwertowanie tablicy na ciąg znaków niż na liczbę.
Ponadto, jak sugeruje cytat Flanagana, ta decyzja projektowa umożliwia pewne rodzaje korzystnych zachowań. Na przykład:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
To zachowanie pozwala porównać tablicę jednoelementową z liczbami i uzyskać oczekiwany wynik.