Pytanie Dodawanie do dwóch pustych obiektów lub pustych tablic w javascript [duplicate]


To pytanie już zawiera odpowiedź:

Po prostu bawiłem się z javascript, gdy znalazłem następujące wyjścia konsoli:

  1. [] + []     // output: ""
  2. [] + {}     // output: [object obiekt]
  3. {} + []     // wyjście: 0
  4. {} + {}     // output: NaN

Czy ktokolwiek mógłby mi wyjaśnić logikę tych wyników? Czuję, że jest to bardzo dziwne zachowanie, ale myślę, że może ma jakąś logikę.

Z góry dziękuję.


11
2018-05-11 11:15


pochodzenie


Westchnienie, wiem, że to pytanie było już wcześniej zadawane, ale SO nie pozwala ci szukać {} i [] ponieważ nie są słowami. - Barmar
1:20 tego filmu - Andy


Odpowiedzi:


Oczekiwane rezultaty

Gdy dodajesz dwie tablice, wszystko działa zgodnie z oczekiwaniami:

[] + []//output''

Konwersja [] do prymitywnych pierwszych prób valueOf() która zwraca samą tablicę (this):

var arr = [];
arr.valueOf() === arr
true

Ponieważ wynik ten nie jest prymitywny, to toString () jest wywoływany jako następny i zwraca pusty ciąg (który jest prymitywny). Dlatego wynik [] + [] jest połączeniem dwóch pustych łańcuchów.

{} + [] // output: 0

Dodanie tablicy i obiektu również odpowiada naszym oczekiwaniom:

 [] + {}//output '[object Object]'

Objaśnienie: przekonwertowanie pustego obiektu na ciąg daje następujący wynik.

 String({})//output: '[object Object]'

Poprzedni wynik jest tworzony przez konkatenację "" i "[object Object]".

Nieoczekiwane wyniki

Rzeczy stają się dziwne, jeśli pierwszy operand z + jest pustym obiektem literalnym (wyniki widoczne na konsoli Firefox):

{} + {}//output: NaN

Co tu się dzieje? Problem polega na tym, że JavaScript interpretuje pierwszy {} jako pusty blok kodu i ignoruje go. The NaN jest zatem obliczany przez ocenę +{} (plus plus drugi {}). Plus, który tutaj widzisz, nie jest binarnym operatorem dodawania, ale unarodowym operatorem prefiksu, który konwertuje swój operand na liczbę, w taki sam sposób, jak Number(). Na przykład:

+"3.65"
3.65

Następujące wyrażenia są równoważne:

+{}
Number({})
Number({}.toString())  // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN

Dlaczego jest pierwszy {} interpretowane jako blok kodu? Ponieważ pełne dane wejściowe są analizowane jako instrukcje, a nawiasy klamrowe na początku instrukcji są interpretowane jako rozpoczynające blok kodu. W związku z tym można naprawić rzeczy, wymuszając przetwarzanie danych wejściowych jako wyrażenie:

({} + {})//output: '[object Object][object Object]'

Argumenty funkcji lub metod są również zawsze analizowane jako wyrażenia:

console.log({} + {})//output: [object Object][object Object]

Po poprzednich wyjaśnieniach nie powinieneś być zaskoczony następującymi wynikami:

{} + []//output: 0

Ponownie, jest to interpretowane jako blok kodu, po którym następuje +[]. Następujące wyrażenia są równoważne:

+[]
Number([])
Number([].toString())  // [].valueOf() isn’t primitive
Number("")
0

Co ciekawe, NPL.Node.js analizuje dane wejściowe inaczej niż Firefox lub Chrome (który korzysta nawet z tego samego silnika JavaScript V8 co Node.js). Poniższe dane wejściowe są analizowane jako wyrażenia, a wyniki są mniej zaskakujące:

{} + {}//output: '[object Object][object Object]'
{} + []//output '[object Object]'

Ma to tę zaletę, że bardziej przypomina wyniki uzyskiwane podczas używania wejścia jako argumenty console.log (). Ale jest również mniej jak używanie danych wejściowych jako instrukcji w programach.

Referencje

Co to jest {} + {} w JavaScript?


9
2018-05-11 11:27