Dlaczego to działa w Node.js
konsoli (testowane w 4.1.1 i 5.3.0), ale nie działa w przeglądarce (testowane w Chrome)? Ten blok kodu powinien tworzyć i wywoływać anonimową funkcję, która rejestruje Ok
.
() => {
console.log('Ok');
}()
Ponadto, chociaż powyższe działa w Node, to nie działa:
n => {
console.log('Ok');
}()
Ani to:
(n) => {
console.log('Ok');
}()
Dziwne jest to, że kiedy parametr jest dodawany, w rzeczywistości rzuca on SyntaxError
w natychmiast wywołującą część.
(n => { console.log("Ok"); })();
działa?(n => { console.log("Ok"); })()
działa nawet w konsoliNode.js
pierwsza wersja już nie działa.Odpowiedzi:
Musisz uczynić go wyrażeniem funkcji zamiast definicji funkcji, która nie potrzebuje nazwy i czyni ją poprawnym JavaScriptem.
Jest odpowiednikiem IIFE
Możliwym powodem, dla którego to działa w Node.js, ale nie w chrome, jest to, że jego parser interpretuje go jako funkcję samowykonującą się, ponieważ
działa dobrze w
Node.js
To jest wyrażenie funkcji i chrome i firefox, a większość przeglądarek interpretuje to w ten sposób. Musisz go wywołać ręcznie.Najpowszechniej akceptowanym sposobem mówienia parserowi, że oczekuje wyrażenia funkcyjnego, jest po prostu umieszczenie go w parenach, ponieważ w JavaScript pareny nie mogą zawierać instrukcji. W tym momencie, gdy parser napotka słowo kluczowe function, wie, że należy je przeanalizować jako wyrażenie funkcji, a nie deklarację funkcji.
Jeśli chodzi o wersję sparametryzowaną , to zadziała.
źródło
Node.js
i faktycznie rejestruje wartość. Moje pytanie brzmi: dlaczego to działa? A dlaczego tak się nie dzieje, gdy dodam parametr?IIFE
i wiem, jak naprawić mój kod. Byłem po prostu ciekawy, dlaczego na przykład mójIIFE
nie działa pon
dodaniu parametru, mimo że działał bez parametru.function(){}()
funkcji strzałkowych? Jeśli chcę, aby wyrażenia funkcyjne uwidocznione przez obiekt funkcji chroniły przed tym.Żadne z nich nie powinno działać bez nawiasów.
Czemu?
Ponieważ zgodnie ze specyfikacją:
Więc ArrowFunction nie może znajdować się po lewej stronie CallExpression .
Co to znaczy w jaki sposób skutecznie
=>
powinny być interpretowane, jest to, że działa na tym samym poziomie, co w rodzaju operatorów przypisania=
,+=
etc.Znaczeniex => {foo}()
nie staje się(x => {foo})()
x => ({foo}())
Więc interpreter decyduje, że(
musiał być zły i zgłasza SyntaxErrorBył to błąd na Babel o tym tutaj , też.
źródło
() => ({console.log('Ok')}())
to już nie działa. Więc tak naprawdę nie interpretuje tego w ten sposób.console.log(...)
nie jest prawidłową nazwą klucza.SyntaxError: Unexpected token (
(wskazując na(
w()
na końcu, a nie(
wconsole.log(...)
).(
Spowodowało, że tłumacz ustąpił po wyczerpujących próbach znalezienia poprawnej interpretacji i idzie „to musi być więc źle”), co i tak może być błędne, ponieważ nie wiem, jak naprawdę jest napisany tłumaczPowodem, dla którego widzisz takie problemy, jest to, że sama konsola próbuje emulować globalny zakres kontekstu, na który obecnie celujesz. Próbuje również przechwycić wartości zwracane z instrukcji i wyrażeń, które piszesz w konsoli, tak aby były wyświetlane jako wyniki. Weź na przykład:
Tutaj wykonuje się tak, jakby to było wyrażenie, ale napisałeś to tak, jakby to była instrukcja. W normalnych skryptach wartość byłaby odrzucana, ale tutaj kod musi zostać zniekształcony wewnętrznie (jak zawijanie całej instrukcji kontekstem funkcji i
return
instrukcją), co powoduje różnego rodzaju dziwne efekty, w tym problemy, których doświadczasz.Jest to również jeden z powodów, dla których nagi kod ES6 w skryptach działa dobrze, ale nie działa w konsoli Chrome Dev Tools.
Spróbuj wykonać to w konsoli Node i Chrome:
W Node lub
<script>
tagu działa dobrze, ale w konsoli dajeUncaught SyntaxError: Unexpected identifier
. Zapewnia również link do źródła, w postaciVMxxx:1
którego możesz kliknąć, aby sprawdzić oceniane źródło, które jest wyświetlane jako:Więc dlaczego to zrobił?
Odpowiedź brzmi: musi przekonwertować Twój kod na wyrażenie, aby wynik mógł zostać zwrócony do wywołującego i wyświetlony w konsoli. Możesz to zrobić, zawijając instrukcję w nawiasach, co czyni ją wyrażeniem, ale także powoduje, że powyższy blok jest niepoprawny składniowo (wyrażenie nie może mieć deklaracji bloku).
Konsola próbuje naprawić te skrajne przypadki, sprytnie podchodząc do kodu, ale myślę, że to wykracza poza zakres tej odpowiedzi. Możesz zgłosić błąd, aby sprawdzić, czy to jest coś, co rozważaliby naprawienie.
Oto dobry przykład czegoś bardzo podobnego:
https://stackoverflow.com/a/28431346/46588
Najbezpieczniejszym sposobem, aby kod działał, jest upewnienie się, że można go uruchomić jako wyrażenie i sprawdzenie
SyntaxError
łącza źródłowego, aby zobaczyć, jaki jest rzeczywisty kod wykonawczy, i przeprowadzić inżynierię wsteczną z tego rozwiązania. Zwykle oznacza parę strategicznie umieszczonych nawiasów.W skrócie: konsola próbuje jak najdokładniej emulować globalny kontekst wykonania, ale ze względu na ograniczenia interakcji z silnikiem v8 i semantyką JavaScript jest to czasami trudne lub niemożliwe do rozwiązania.
źródło
Zadałem takie pytanie:
a to jest odpowiedź Kyle'a Simpsona:
vs
- getify (@getify) 12 czerwca 2020
źródło
console.log(x)(4)
.