Dlaczego {} + {} nie jest już NaN w konsoli Chrome?


144

Zauważyłem dzisiaj, że Chrome 49 nie wyświetla już wyjścia NaNpodczas wpisywania {}+{}w konsoli. Zamiast tego wyprowadza ciąg [object Object][object Object].

Dlaczego to? Czy zmienił się język?


13
wygląda na to, że chrome teraz traktuje tę operację jako konkatację, a nie dodawanie. DLACZEGO to nie wiem, dlatego to jest komentarz, a nie odpowiedź :) spróbuj, var e = {}; e.toString()a zobaczysz, o co mi chodzi
user428517

19
„Czy zmienił się język?” Nie.
Felix Kling

6
@FelixKling Czy język się zmieni? ...Nie. : c
kot

18
Może WATMAN miał z tym coś wspólnego?
rickster

1
@rickster, tak to znalazłem. Odtwarzałem to na potrzeby prezentacji.
Filip Haglund

Odpowiedzi:


152

Chrome devtools teraz automatycznie zawija wszystko, co zaczyna się od {i kończy }w niejawnej parze nawiasów ( patrz kod ), aby wymusić jego ocenę jako wyrażenie. W ten sposób {}tworzy teraz pusty obiekt. Możesz to zobaczyć, jeśli wrócisz do historii ( ), poprzednia linia będzie zawarta w (…).

Czemu? Nie wiem, ale domyślam się, że zmniejsza to zamieszanie u początkujących, którzy nie wiedzą o dosłowności blok kontra obiekt, a także jest bardziej pomocne, jeśli chcesz po prostu ocenić wyrażenie.

I faktycznie to jest rozumowanie, jak omówiono w błędzie 499864 . Czysta wygoda. A ponieważ węzeł REPL również to miał ( patrz kod ).


182
Głupi Chrome {a:1}),({b:2}powinien generować błąd, a nie tworzyć obiektu.
Oriol,

29
Tak się dzieje, gdy analizujesz dowolnie głęboko zagnieżdżone struktury za pomocą wyrażenia regularnego stackoverflow.com/questions/1732348/ ...
Filip Haglund

4
Nie mam pojęcia dlaczego, ale w jakiś sposób, kiedy widzę tam swoje wiadomości, czuję się „sławny”, chociaż ta strona jest tak samo publiczna jak ta: D Dziwny problem ze StackOverflow. Oto moja starsza odpowiedź na temat problemu stackoverflow.com/questions/17268468/…
Benjamin Gruenbaum

3
Nie podoba mi się obecne wdrożenie i planuję to naprawić. bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak

1
@Zirak Powodzenia w naprawianiu tych śmieci, IMO należy je jak najszybciej wycofać. Ale jeśli chcesz to ulepszyć, rozważ dodanie nowej linii przed wstawionym tekstem )na wypadek, gdyby był w komentarzu, np. {a:3} // :-}Nadal może tworzyć obiekt.
Oriol,

44

Jeśli po sprawdzeniu tego naciśniesz strzałkę w górę, zauważysz, że zamiast {} + {}tego wyświetla się ({} + {}), co powoduje "[object Object][object Object]".

Dla porównania, w Firefoksie {} + {}nadal wyświetla się NaN, ale jeśli to zrobisz ({} + {}), również wyświetla "[object Object][object Object]".

Wygląda więc na to, że Chrome automatycznie dodaje otaczający nawias, gdy widzi tę operację.


22
ta odpowiedź jest poprawna. ale wow, stary, nie jestem pewien, czy podoba mi się ten chrom, który to robi. zły Google.
user428517

1
@sgroves Chciałbym sprawdzić, czy to jest to samo w Canary i czy zostało to zrobione celowo, czy w rzeczywistości jest to błąd.
J. Titus,

8
{} + {}gdy nie jest „oczyszczony”, ({} + {})jest traktowany jako + {}ponieważ {}jest analizowany jako pusty blok.
Gregory Nisbet,

7
Dlaczego miałby zwrócić NaN w pierwszej kolejności?
0x499602D2

25
@ 0x499602D2: Ponieważ jeśli nie wykonasz parenów (lub w inny sposób nie spowodujesz, że parser przestawi się na oczekiwanie wyrażenia, a nie instrukcji), inicjał {}jest tylko pustym blokiem kodu i jest ignorowany, pozostawiając nas +{}, który jest jednoargumentowym +i pustym obiektem inicjator. +będzie zmuszania jej argumentu numeru, który polega na przekształceniu obiektu na pierwotną (która w końcu jest toStringw tym przypadku, w wyniku "[object Object]"), a więc mamy +"[object Object]"która NaNdlatego "[object Object]"nie może być przekształcany do odpowiedniej liczby.
TJ Crowder

4

Od Chrome 54 w odniesieniu do konsoli:

📎- „Przekonwertowałem ten blok na obiekt dla ciebie” -Clippy Niestety sam dodałem cytat Clippy. Konsola nie podaje żadnych informacji o tym, co dla Ciebie zrobiła.

Nowe zasady są niewiarygodnie proste , dzięki czemu nie musimy mozolnie wpisywać tych 2 trudnych znaków o=lub 0,przed wklejeniem literali obiektu do konsoli:

  • Jeśli masz kod, który zaczyna się od: opcjonalnej białej spacji (bez komentarzy), po której następuje {;
  • a kod ten mógłby zostać zinterpretowany jako obiekt;
  • i po tym obiekcie nie następuje żaden inny kod, chyba że:
  • kod po pierwszym obiekcie jest operatorem binarnym,
  • wtedy może być tyle operacji, ile chcesz, łącznie z grupami
  • pod warunkiem, że operator końcowy ma literał Object po prawej stronie;
  • a ten ostateczny Obiekt nie został zgrupowany w parens
  • i ten kod nie jest zakończony średnikiem
  • i nie ma komentarzy po kodzie (komentarze wewnętrzne są dozwolone, o ile nie znajdują się na pozycji początkowej lub końcowej)
  • wtedy i tylko wtedy twój JavaScript (który może, ale nie musi być prawidłowym kodem) zostanie ponownie odczytany jako prawidłowy obiekt. Nie zostaniesz poinformowany, że Twój kod został ponownie zinterpretowany.

{wat:1}),({wat:2} To w końcu znowu błąd.

{let i=0;var increment=_=>i++} w końcu jest poprawnie dozwolone, co jest całkiem niezłym sposobem na zamykanie.

Jednak poniższy obiekt jest niepoprawny, jest to tylko wygoda, o której wspomniał @Bergi, interpretuje JS źle, aby ci pomóc! Specyfikacja mówi, że jest to blok z oznaczoną instrukcją „foo” z literałem 1, który nie jest do niczego przypisany.

{foo:1}

Powyższe powinno być takie samo jak

if(1) {
    foo: 1
}

Poniższy tekst jest poprawnie traktowany jako blok ... ponieważ ma przed sobą komentarz!

//magic comment
{foo:1}

Więc to jest:

{foo:1}
//also magic

To jest obiekt:

{foo:
//not so magic comment
1}

To jest błąd

//not so magic comment
{foo:1}.foo

Więc to jest:

{foo:1}.foo

Jest okej:

1..wat

undefined

więc jest to:

['foo'][0]

Następny jest poprawnie zinterpretowany jako obiekt wbity w pozycję wyrażenia za pomocą a, 0,co generalnie jest sposobem, w jaki jednoznacznie upewniamy się, że zamiast instrukcji mamy wyrażenie.

0,{foo:1}.foo

Nie rozumiem, dlaczego zawijają wartość w pareny. JS ma kilka absurdalnych decyzji projektowych, ale próba sprawienia, by zachowywał się lepiej w tej jednej sytuacji, tak naprawdę nie wchodzi w grę, konsola musi poprawnie uruchamiać JS i musimy być pewni, że chrome nie tylko zgaduje, że myśli, że my naprawdę chciał zrobić coś innego.

Jeśli nie lubisz operatorów przecinkowych, możesz użyć przypisania

x = {foo:1}.foo

Ponieważ w obecnej postaci

{} + {} + {}

"[object Object][object Object][object Object]"

;{} + {} + {}

"NaN[object Object]"

Szalony i konsekwentny, z którym mogę sobie poradzić ... szalony i niekonsekwentny nie, dziękuję!


REPL nie jest językiem, to REPL. Między innymi przekazuje ciągi do języka . Oto kilka rzeczy, które Chrome REPL robi, czego sam język nie robi . Są całkiem przydatne, więc cieszę się, że nie trzymali się prostego języka.
gman

@gman A REPL Odczytuje ciąg, ocenia go, drukuje wyniki, a następnie przygotowuje do odczytania następnego fragmentu kodu dynamicznego. Nic na połączonej stronie nie zawiera nieprawidłowego kodu JavaScript. Zmienna „$ _” ograniczona do kontekstu konsoli jest oczywiście wygodą, która ma sens tylko w REPL. Niemniej jednak „$ _” jest prawidłową nazwą zmiennej, reszta to zwykłe funkcje i klasy wywoływane przez normalny JavaScript.
James Wakefield

Nie jestem pewien, o co ci chodzi. Chodzi mi o to, że język to jedno, a środowisko, w którym działa, to drugie. W swojej odpowiedzi podałeś przykład. W JS {foo:1}i {foo:1}//produkuj to samo. W Chrome JS REPL tego nie robią. REPL robi coś więcej niż tylko ocenę JS. Przetwarza struny i decyduje się na różne rzeczy.
gman

var x = eval('{a:1}')W prawidłowym JavaScript x jest teraz 1, a nie bardziej intuicyjnym obiektem {a: 1}. Tak, to dziwne, ale nie możesz tak po prostu zmienić języka, ponieważ robi on dziwne rzeczy. Wszystko inne niż ciągi JSON jest interpretowane jako JavaScript i oceniane. Wpisanie 0,przed wklejeniem JSON nie jest trudne, alternatywnie byłbym zadowolony z ostrzeżenia, że ​​ciąg został zinterpretowany jako obiekt zamiast JavaScript dla wygody.
James Wakefield
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.