Pytanie skierowane jest do osób, które zastanawiały się nad stylem kodu w kontekście nadchodzącego ECMAScript 6 (Harmony) i które już pracowały z tym językiem.
Za pomocą () => {}
i function () {}
otrzymujemy dwa bardzo podobne sposoby pisania funkcji w ES6. W innych językach funkcje lambda często wyróżniają się anonimowością, ale w ECMAScript każda funkcja może być anonimowa. Każdy z tych dwóch typów ma unikalne domeny użytkowania (a mianowicie kiedy this
musi być albo wyraźnie związany, albo jawnie nie związany). Pomiędzy tymi domenami istnieje ogromna liczba przypadków, w których wystarczy jedna z notacji.
Funkcje strzałek w ES6 mają co najmniej dwa ograniczenia:
- Nie pracuj z
new
i nie można go używać podczas tworzeniaprototype
- Naprawiono
this
ograniczenie zakresu podczas inicjalizacji
Pomijając te dwa ograniczenia, funkcje strzałek mogłyby teoretycznie zastąpić zwykłe funkcje prawie wszędzie. Jakie jest właściwe podejście z wykorzystaniem ich w praktyce? Czy należy używać funkcji strzałek, np .:
- „wszędzie, gdzie działają”, tzn. wszędzie funkcja nie musi być agnostyczna wobec
this
zmiennej i nie tworzymy obiektu. - tylko „wszędzie tam, gdzie są potrzebne”, tj. detektory zdarzeń, przekroczenia limitu czasu, które muszą być ograniczone do określonego zakresu
- z funkcjami „krótkimi”, ale nie z funkcjami „długimi”
- tylko z funkcjami, które nie zawierają innej funkcji strzałki
To, czego szukam, jest wskazówką dotyczącą wyboru odpowiedniej notacji funkcji w przyszłej wersji ECMAScript. Wytyczne będą musiały być jasne, aby można było ich nauczyć programistów w zespole, i muszą być spójne, aby nie wymagały ciągłego refaktoryzacji tam iz powrotem od jednej notacji funkcji do drugiej.
Fixed this bound to scope at initialisation
ograniczenie?this
można wykonać za pomocą zwykłych funkcji, ale nie za pomocą funkcji strzałek.Fixed this bound to scope at initialisation
za ograniczenie. :) Spójrz na ten artykuł: exploringjs.com/es6/ch_arrow-functions.htmlOdpowiedzi:
Jakiś czas temu nasz zespół przeprowadził migrację całego kodu (średniej wielkości aplikacji AngularJS) do JavaScript skompilowanego przy użyciu
TraceurBabel . Teraz używam następującej ogólnej zasady dla funkcji w ES6 i późniejszych:function
w zakresie globalnym i dlaObject.prototype
właściwości.class
dla konstruktorów obiektów.=>
wszędzie indziej.Po co używać funkcji strzałek prawie wszędzie?
thisObject
tak samo jak root. Jeśli nawet jedno standardowe wywołanie zwrotne funkcji zostanie zmieszane z kilkoma funkcjami strzałek, istnieje szansa, że zakres zostanie pomieszany.function
natychmiast wyróżnia się w określaniu zakresu. Deweloper może zawsze sprawdzić następną wyższąfunction
instrukcję, aby zobaczyć, co tothisObject
jest.Dlaczego zawsze używamy regularnych funkcji w zakresie globalnym lub zakresie modułu?
thisObject
.window
Przedmiot (zakres globalny) jest najlepiej skierowana wyraźnie.Object.prototype
definicji żyje w zasięgu globalnym (pomyślString.prototype.truncate
itd.), A te i tak muszą być typufunction
. Konsekwentne stosowaniefunction
w zakresie globalnym pomaga uniknąć błędów.function foo(){}
niżconst foo = () => {}
- w szczególności poza innymi wywołaniami funkcji. (2) Nazwa funkcji jest wyświetlana w śladach stosu. Nazwanie każdego wewnętrznego wywołania zwrotnego byłoby nudne, jednak nazwanie wszystkich funkcji publicznych jest prawdopodobnie dobrym pomysłem.Konstruktory obiektów
Próba utworzenia instancji funkcji strzałki generuje wyjątek:
Jedną z kluczowych zalet funkcji nad funkcjami strzałek jest zatem to, że działają one podwójnie jako konstruktory obiektów:
Jednak funkcjonalnie identyczna definicja klasy roboczej 2 ES Harmony jest prawie tak kompaktowa:
Oczekuję, że stosowanie poprzedniej notacji ostatecznie zostanie zniechęcone. Notacja konstruktora obiektów może być nadal używana przez niektóre proste fabryki anonimowych obiektów, w których obiekty są generowane programowo, ale niewiele więcej.
Tam, gdzie potrzebny jest konstruktor obiektów, należy rozważyć zamianę funkcji na
class
pokazaną powyżej. Składnia działa również z anonimowymi funkcjami / klasami.Czytelność funkcji strzałek
Prawdopodobnie najlepszym argumentem za trzymaniem się funkcji regularnych - do diabła z bezpieczeństwem zakresu - byłoby to, że funkcje strzałek są mniej czytelne niż funkcje zwykłe. Jeśli kod nie działa przede wszystkim, funkcje strzałek mogą nie wydawać się konieczne, a gdy funkcje strzałek nie są używane konsekwentnie, wyglądają brzydko.
ECMAScript zmienił się nieco, odkąd ECMAScript 5.1 dał nam funkcjonalność
Array.forEach
,Array.map
a wszystkie te funkcje programowania funkcjonalnego, które pozwalają nam korzystać z funkcji, w których wcześniej używane byłyby pętle for. Asynchroniczny JavaScript znacznie wystartował. ES6 wyśle równieżPromise
obiekt, co oznacza jeszcze więcej anonimowych funkcji. Nie ma powrotu do programowania funkcjonalnego. W funkcjonalnym JavaScript funkcje strzałek są lepsze niż zwykłe funkcje.Weźmy na przykład ten (szczególnie mylący) fragment kodu 3 :
Ten sam fragment kodu z normalnymi funkcjami:
Podczas gdy dowolną z funkcji strzałek można zastąpić funkcją standardową, niewiele można na tym zyskać. Która wersja jest bardziej czytelna? Powiedziałbym pierwszy.
Myślę, że z czasem pytanie, czy używać funkcji strzałek, czy funkcji regularnych, będzie mniej istotne. Większość funkcji albo stanie się metodami klasowymi, które usuwają
function
słowo kluczowe, albo staną się klasami. Funkcje będą nadal używane do łatania klas poprzezObject.prototype
. Tymczasem sugeruję zarezerwowaniefunction
słowa kluczowego na wszystko, co naprawdę powinno być metodą klasową lub klasą.Notatki
extend
słowa kluczowego. Niewielka różnica polega na tym, że deklaracje klas są stałymi, podczas gdy deklaracje funkcji nie.źródło
function
jest to, że nie chceszthis
być związany, prawda? Moim najczęstszym scenariuszem są zdarzenia, w których możesz chciećthis
odwoływać się do obiektu (zwykle węzła DOM), który wywołał zdarzenie.=>
wynika, że z czasem wyglądam lepiej. Wątpię, aby nie-programiści bardzo inaczej postrzegali te dwa przykłady. Jeśli piszesz kod ES2016, zwykle nie będziesz używać tak wielu funkcji strzałek. W tym przykładzie, używając asynchronizacji / oczekiwania i interpretacji tablic, uzyskasz tylko jedną funkcję strzałki wreduce()
wywołaniu.Zgodnie z propozycją , strzały miały na celu „rozwiązanie i rozwiązanie kilku typowych problemów związanych z tradycyjnym
Function Expression
”. Zamierzali poprawić sprawy, wiążącthis
leksykalnie i oferując zwięzłą składnię.Jednak,
this
leksykalnieDlatego funkcje strzałek stwarzają możliwość pomyłek i błędów i należy je wyłączyć ze słownika programisty JavaScript, zastępując je
function
wyłącznie.Odnośnie leksykalnej
this
this
jest problematyczne:Funkcje strzałek mają rozwiązać problem polegający na tym, że musimy uzyskać dostęp do właściwości
this
wewnątrz wywołania zwrotnego. Jest już na to kilka sposobów: Można przypisaćthis
do zmiennej, użyćbind
lub użyć trzeciego argumentu dostępnego wArray
metodach agregujących. Jednak strzałki wydają się być najprostszym obejściem, więc metodę można by zmienić w następujący sposób:Zastanów się jednak, czy kod używał biblioteki takiej jak jQuery, której metody wiążą się
this
specjalnie. Terazthis
mamy do czynienia z dwiema wartościami:Musimy używać
function
,each
aby wiązać sięthis
dynamicznie. Nie możemy tutaj użyć funkcji strzałki.Radzenie sobie z wieloma
this
wartościami może być również mylące, ponieważ trudno jest ustalić, o którymthis
autor mówił:Czy autor rzeczywiście chciał zadzwonić
Book.prototype.reformat
? A może zapomniał związaćthis
i zamierzał zadzwonićReader.prototype.reformat
? Jeśli zmienimy moduł obsługi na funkcję strzałki, podobnie będziemy się zastanawiać, czy autor chciał dynamikithis
, ale wybrał strzałkę, ponieważ pasuje do jednej linii:Można postawić: „Czy to wyjątkowe, że strzałki mogą być czasem niewłaściwą funkcją? Być może, jeśli rzadko potrzebujemy
this
wartości dynamicznych , to nadal byłoby dobrze używać strzałek przez większość czasu”.Ale zadaj sobie następujące pytanie: „Czy warto byłoby debugować kod i stwierdzić, że wynikiem błędu był„ przypadek na krawędzi ”?” Wolałbym unikać problemów nie tylko przez większość czasu, ale także 100% czasu.
Jest lepszy sposób: Zawsze używaj
function
(więcthis
zawsze może być dynamicznie związany) i zawsze odwołuj sięthis
przez zmienną. Zmienne są leksykalne i przyjmują wiele nazw. Przypisaniethis
do zmiennej wyjaśni twoje intencje:Co więcej, zawsze przypisywanie
this
do zmiennej (nawet gdy istnieje jednathis
lub żadna inna funkcja) zapewnia, że intencje pozostają jasne nawet po zmianie kodu.Ponadto dynamika
this
nie jest niczym wyjątkowym. jQuery jest używany na ponad 50 milionach stron internetowych (od tego pisania w lutym 2016 r.). Oto inne interfejsy API wiążące sięthis
dynamicznie:this
.this
.this
.EventTarget
zthis
.this
.(Statystyki za pośrednictwem http://trends.builtwith.com/javascript/jQuery i https://www.npmjs.com .)
Prawdopodobnie już potrzebujesz
this
powiązań dynamicznych .this
Czasem oczekuje się leksyki , ale czasem nie; tak jakthis
czasami oczekuje się dynamiki , ale czasem nie. Na szczęście istnieje lepszy sposób, który zawsze wytwarza i komunikuje oczekiwane wiązanie.Odnośnie skróconej składni
Funkcje strzałek zapewniły „krótszą formę składniową” dla funkcji. Ale czy te krótsze funkcje sprawią, że odniesiesz większy sukces?
Czy
x => x * x
„łatwiej jest czytać” niżfunction (x) { return x * x; }
? Być może jest tak, ponieważ bardziej prawdopodobne jest wygenerowanie jednego, krótkiego wiersza kodu. Według Dysona Wpływ prędkości odczytu i długości linii na skuteczność odczytu z ekranu ,Podobne uzasadnienia dotyczą operatora warunkowego (trójskładnikowego) i
if
instrukcji jednowierszowych .Czy naprawdę piszesz proste funkcje matematyczne reklamowane we wniosku ? Moje domeny nie są matematyczne, więc moje podprogramy rzadko są tak eleganckie. Często widzę, że funkcje strzałek przekraczają limit kolumn i zawijają się do innej linii ze względu na edytor lub przewodnik po stylu, który niweluje „czytelność” według definicji Dysona.
Można by postawić: „A może po prostu użyć krótkiej wersji do krótkich funkcji, jeśli to możliwe?” Ale teraz reguła stylistyczna stoi w sprzeczności z ograniczeniami językowymi: „Spróbuj użyć możliwie najkrótszej notacji funkcji, pamiętając, że czasami tylko najdłuższa notacja wiąże się
this
zgodnie z oczekiwaniami”. Takie pomieszanie sprawia, że strzały są szczególnie podatne na niewłaściwe użycie.Istnieje wiele problemów ze składnią funkcji strzałek:
Obie te funkcje są poprawne pod względem składniowym. Ale
doSomethingElse(x);
nie ma go w treścib
, jest to po prostu słabo wcięte oświadczenie najwyższego poziomu.Po rozwinięciu do postaci bloku nie ma już domniemania
return
, którego przywrócenie można zapomnieć. Ale to wyrażenie mogło mieć jedynie na celu wywołanie efektu ubocznego, więc kto wie, czy wyraźnereturn
będzie konieczne w przyszłości?To, co może być przeznaczone jako parametr spoczynkowy, można przeanalizować jako operator rozkładania:
Przypisanie można pomylić z domyślnymi argumentami:
Bloki wyglądają jak obiekty:
Co to znaczy?
Czy autor miał zamiar utworzyć brak operacji lub funkcję zwracającą pusty obiekt? (Mając to na uwadze, powinniśmy zawsze umieszczać
{
po=>
? Powinniśmy ograniczyć się tylko do składni wyrażeń? To by jeszcze bardziej zmniejszyć częstotliwość strzałkami.)=>
wygląda<=
i>=
:Aby natychmiast wywołać wyrażenie funkcji strzałki, należy umieścić je
()
na zewnątrz, ale umieszczenie()
w środku jest prawidłowe i może być zamierzone.Chociaż, jeśli ktoś pisze
(() => doSomething()());
z zamiarem napisania natychmiast wywołanego wyrażenia funkcyjnego, po prostu nic się nie wydarzy.Trudno argumentować, że funkcje strzałek są „bardziej zrozumiałe”, biorąc pod uwagę wszystkie powyższe przypadki. Jeden mógł poznać wszystkie szczególne zasady niezbędne do wykorzystania tej składni. Czy to naprawdę jest tego warte?
Składnia
function
jest wyjątkowo uogólniona. Używaniefunction
wyłącznie oznacza, że sam język zapobiega pisaniu mylącego kodu. Aby napisać procedury, które powinny być rozumiane syntaktycznie we wszystkich przypadkach, wybieramfunction
.Jeśli chodzi o wytyczne
Prosisz o wytyczne, które muszą być „jasne” i „spójne”. Użycie funkcji strzałek ostatecznie spowoduje powstanie poprawnego pod względem składniowym, logicznie niepoprawnego kodu, z obiema formami funkcji splecionymi, sensownie i arbitralnie. Dlatego oferuję:
Wytyczne dotyczące notacji funkcji w ES6:
function
.this
do zmiennej. Nie używać() => {}
.źródło
self
zamiast tego. Podane pułapki funkcji strzałek również są ważne i obowiązują tu te same standardy, co w przypadku innych instrukcji, które mogą być stosowane bez nawiasów klamrowych; w przeciwnym razie myślę, że z twoim argumentem równie dobrze można promować wszędzie funkcje strzałek.this
jest problemem Javascript. Zamiast być niejawnie związany,this
powinien zostać przekazany jako jawny argument.Funkcje strzałek zostały stworzone w celu uproszczenia funkcji
scope
i rozwiązaniathis
słowa kluczowego poprzez uproszczenie go. Wykorzystują=>
składnię, która wygląda jak strzała.Uwaga: Nie zastępuje istniejących funkcji. Jeśli zastąpisz każdą składnię funkcji funkcjami strzałek, nie będzie ona działać we wszystkich przypadkach.
Spójrzmy na istniejącą składnię ES5. Gdyby
this
słowo kluczowe znajdowało się w metodzie obiektu (funkcja należąca do obiektu), do czego by się odnosiło?Powyższy fragment odnosi się do
object
i wypisuje nazwę"RajiniKanth"
. Przyjrzyjmy się poniższemu fragmentowi i zobaczmy, o co tu chodzi.A co jeśli
this
słowo kluczowe było w środkumethod’s function
?Tutaj to będzie dotyczyć
window object
niżinner function
jak jej wypadłscope
. Ponieważthis
zawsze odwołuje się do właściciela funkcji, w której się znajduje, w tym przypadku - ponieważ nie jest już objęty zakresem - obiektu okna / obiektu globalnego.Gdy jest w
object
metodzie -function
właścicielem jest obiekt. Zatem to słowo kluczowe jest powiązane z obiektem. Jednak gdy znajduje się wewnątrz funkcji, albo samodzielnie, albo w innej metodzie, zawsze będzie odnosić się dowindow/global
obiektu.Istnieją sposoby rozwiązania tego problemu w nas
ES5
samych, przyjrzyjmy się temu przed zanurzeniem się w funkcjach strzałek ES6, w jaki sposób je rozwiązać.Zazwyczaj tworzysz zmienną poza funkcją wewnętrzną metody. Teraz
‘forEach’
zyskuje metoda dostępu dothis
, a tym samym naobject’s
właściwości i ich wartości.za pomocą,
bind
aby dołączyćthis
słowo kluczowe odnoszące się do metody domethod’s inner function
.Teraz dzięki
ES6
funkcji strzałki możemy uporać się zlexical scoping
problemem w prostszy sposób.Arrow functions
są bardziej podobne do instrukcji funkcyjnych, z tą różnicą, żebind
toparent scope
. Jeżeliarrow function is in top scope
,this
argumentem będzie dotyczyćwindow/global scope
, natomiast funkcja strzałka wewnątrz regularnie funkcji będą mieć ten argument taki sam jak jego zewnętrznej funkcji.Z
arrow
funkcjamithis
jest związanyscope
w momencie tworzenia i nie można go zmienić. Nowy operator, powiązanie, wywołanie i zastosowanie nie mają na to wpływu.W powyższym przykładzie straciliśmy nad tym kontrolę. Możemy rozwiązać powyższy przykład, używając zmiennej odwołania
this
lub używającbind
. Z ES6, staje się łatwiejszy w zarządzaniuthis
, jak jego związanylexical scoping
.Kiedy nie do funkcji strzałek
Wewnątrz obiektu dosłownie.
Actor.getName
jest zdefiniowany za pomocą funkcji strzałki, ale przy wywołaniu alarmuje niezdefiniowany, ponieważthis.name
jestundefined
tak, jak pozostaje kontekstwindow
.Dzieje się tak, ponieważ funkcja strzałki wiąże kontekst leksykalnie z
window object
... tzn. Zasięgiem zewnętrznym. Wykonywaniethis.name
jest równoważne zwindow.name
, co jest niezdefiniowane.Prototyp obiektu
Ta sama zasada obowiązuje przy definiowaniu metod na
prototype object
. Zamiast używać funkcji strzałki do definiowania metody sayCatName, która powoduje niepoprawnecontext window
:Wywoływanie konstruktorów
this
w wywołaniu konstrukcji jest nowo utworzony obiekt. Podczas wykonywania nowej Fn (), kontekstconstructor Fn
jest nowy obiekt:this instanceof Fn === true
.this
jest konfigurowany z otaczającego kontekstu, tj. zewnętrznego zasięgu, który powoduje, że nie jest on przypisywany do nowo utworzonego obiektu.Oddzwonienie z kontekstem dynamicznym
Funkcja strzałki wiąże
context
statycznie przy deklaracji i nie jest możliwe uczynienie go dynamicznym. Dołączanie detektorów zdarzeń do elementów DOM jest częstym zadaniem w programowaniu po stronie klienta. Zdarzenie wyzwala funkcję modułu obsługi z tym jako elementem docelowym.this
to okno w funkcji strzałki zdefiniowane w kontekście globalnym. Gdy nastąpi zdarzenie kliknięcia, przeglądarka próbuje wywołać funkcję modułu obsługi z kontekstem przycisku, ale funkcja strzałki nie zmienia wcześniej zdefiniowanego kontekstu.this.innerHTML
jest równoważnewindow.innerHTML
i nie ma sensu.Musisz zastosować wyrażenie funkcyjne, które pozwala to zmienić w zależności od elementu docelowego:
Gdy użytkownik kliknie przycisk, w funkcji modułu obsługi jest to przycisk. W ten sposób
this.innerHTML = 'Clicked button'
poprawnie modyfikuje tekst przycisku, aby odzwierciedlić status kliknięcia.Odnośniki: https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
źródło
using bind to attach the this keyword that refers to the method to the method’s inner function.
ma błędy składniowe.var Actor = { name: 'RajiniKanth', movies: ['Kabali', 'Sivaji', 'Baba'], showMovies: function() { this.movies.forEach(function(movie){ alert(this.name + ' has acted in ' + movie); }.bind(this)) } }; Actor.showMovies();
Użycie: Wszystkie funkcje ES5 należy zastąpić funkcjami strzałek ES6, z wyjątkiem następujących scenariuszy:
NIE należy używać funkcji strzałek:
this
/arguments
w funkcjithis
/arguments
zależą od zewnętrznego kontekstu.constructor
this
.this
(co powinno być samym obiektem).Pozwól nam zrozumieć niektóre warianty funkcji strzałek, aby lepiej zrozumieć:
Wariant 1 : Kiedy chcemy przekazać więcej niż jeden argument do funkcji i zwrócić z niej pewną wartość.
Wersja ES5 :
Wersja ES6 :
Uwaga:
function
słowo kluczowe NIE jest wymagane.=>
jest wymagane.{}
są opcjonalne, jeśli nie podamy,{}
return
jest domyślnie dodany przez JavaScript, a gdy podamy,{}
musimy dodać,return
jeśli jest to potrzebne.Wariant 2 : Gdy chcemy przekazać TYLKO jeden argument do funkcji i zwrócić z niej pewną wartość.
Wersja ES5 :
Wersja ES6 :
Uwaga: przekazując tylko jeden argument, możemy pominąć nawias
()
.Wariant 3 : Kiedy NIE chcemy przekazać żadnego argumentu do funkcji i NIE chcemy zwrócić żadnej wartości.
Wersja ES5 :
Wersja ES6 :
Wariant 4 : Kiedy chcemy jawnie powrócić z funkcji strzałek.
Wersja ES6 :
Wariant 5 : Kiedy chcemy zwrócić obiekt z funkcji strzałek.
Wersja ES6 :
Uwaga: Musimy owinąć obiekt w nawiasach, w
()
przeciwnym razie JavaScript nie będzie w stanie odróżnić bloku od obiektu.Wariant 6 : Funkcje strzałek NIE mają
arguments
własnych obiektów (tablicowych), zależą od zewnętrznego kontekstuarguments
.Wersja ES6 :
Uwaga:
foo
jest funkcją ES5, zarguments
tablicy jak przedmiotu i przekazany do argumentu jest2
więcarguments[0]
dofoo
2.abc
jest funkcja ES6 strzałka ponieważ nie ma własnearguments
stąd drukujearguments[0]
zfoo
To zewnętrznej kontekście zamiast.Wariant 7 : Funkcje strzałek NIE mają
this
własnych, zależą od zewnętrznego kontekstuthis
Wersja ES5 :
Uwaga: Wywołanie zwrotne przekazane do setTimeout jest funkcją ES5 i ma swoją własną,
this
która nie jest zdefiniowana wuse-strict
środowisku, dlatego otrzymujemy dane wyjściowe:Wersja ES6 :
Uwaga: Przekazane wywołanie zwrotne
setTimeout
jest funkcją strzałki ES6 i NIE ma własnej,this
więc bierze ją z zewnętrznego kontekstu,greetUser
który mathis
,obj6
dlatego otrzymujemy dane wyjściowe:Różne: Nie możemy używać
new
z funkcjami strzałek. Funkcje strzałek nie mająprototype
właściwości. NIE mamy powiązania,this
kiedy funkcja strzałki jest wywoływana przezapply
lubcall
.źródło
Oprócz świetnych dotychczasowych odpowiedzi chciałbym przedstawić zupełnie inny powód, dla którego funkcje strzałek są w pewnym sensie zasadniczo lepsze niż „zwykłe” funkcje JavaScript. Dla celów dyskusji załóżmy tymczasowo, że używamy sprawdzania typów, takiego jak TypeScript lub „Flow” Facebooka. Rozważ następujący moduł zabawki, który jest prawidłowym kodem ECMAScript 6 oraz adnotacjami typu Flow: (Na końcu tej odpowiedzi dołączę kod bez typu, który realistycznie powstałby z Babel, aby można go było uruchomić).
Zobaczmy teraz, co się stanie, gdy użyjemy klasy C z innego modułu, na przykład:
Jak widzisz, sprawdzanie typów nie powiodło się tutaj: f2 miał zwrócić liczbę, ale zwrócił ciąg!
Gorzej, wydaje się, że nie można sobie wyobrazić sprawdzania typu nie obsługuje zwykłych funkcji JavaScript (bez strzałek), ponieważ „to” z f2 nie występuje na liście argumentów f2, więc nie można dodać wymaganego typu „to” jako adnotacja do f2.
Czy ten problem dotyczy także osób, które nie używają sprawdzania typów? Myślę, że tak, ponieważ nawet jeśli nie mamy żadnych typów statycznych, myślimy, jakby tam były. („Pierwsze parametry muszą być liczbą, drugie ciągiem znaków itp.) Ukryty„ ten ”instrument, który może, ale nie musi być użyty w ciele funkcji, utrudnia naszą mentalną księgowość.
Oto uruchamialna, nietypowa wersja, którą wyprodukowałby Babel:
źródło
Wolę używać funkcji strzałek przez cały czas, gdy dostęp do lokalnego
this
nie jest potrzebny, ponieważ funkcja strzałki nie wiąże tego, argumentów, super lub new.target .źródło
Nadal trzymam się wszystkiego, co napisałem w pierwszej odpowiedzi w tym wątku. Jednak moja opinia na temat stylu kodu rozwinęła się od tego czasu, więc mam nową odpowiedź na to pytanie, która opiera się na moim ostatnim.
Odnośnie leksykalnej
this
W ostatniej odpowiedzi umyślnie porzuciłem przekonanie, które mam na temat tego języka, ponieważ nie było to bezpośrednio związane z argumentem, który przedstawiłem. Niemniej jednak, bez wyraźnego stwierdzenia tego, rozumiem, dlaczego wiele osób po prostu nie zgadza się z moim zaleceniem, aby nie używać strzał, gdy uznają je za przydatne.
Wierzę w to: nie powinniśmy używać
this
w pierwszej kolejności. Dlatego jeśli ktoś celowo unika używaniathis
w swoim kodzie, wówczas „leksykalnathis
” funkcja strzałek ma niewielką lub żadną wartość. Ponadto, przy założeniu, żethis
jest to coś złego, traktowanie strzałythis
jest mniej „dobrem”; zamiast tego jest bardziej formą kontroli obrażeń dla innej funkcji w złym języku.Wydaje mi się, że albo nie zdarza się to niektórym ludziom, ale nawet tym, którym to robi, muszą oni zawsze znajdować się w bazach kodowych, w których
this
Wydaje pojawia się sto razy na plik, a wszystko to (lub dużo) kontroli szkód jest wszystkim rozsądna osoba może mieć nadzieję. Tak więc strzały mogą być dobre, jeśli poprawią złą sytuację.Nawet jeśli łatwiej jest pisać kod ze
this
strzałkami niż bez nich, zasady używania strzałek pozostają bardzo złożone (patrz: aktualny wątek). Zatem wytyczne nie są ani „jasne”, ani „spójne”, tak jak prosiłeś. Nawet jeśli programiści wiedzą o dwuznacznościach strzał, myślę, że i tak wzruszają ramionami i akceptują je, ponieważ wartość leksykalnathis
przesłania je.Wszystko to jest wstępem do następującej realizacji: jeśli się nie używa
this
, wówczas dwuznaczność dotyczącathis
tych strzałek zwykle staje się nieistotna. Strzały stają się w tym kontekście bardziej neutralne.Odnośnie skróconej składni
Kiedy napisałem swoją pierwszą odpowiedź, byłem zdania, że nawet niewolnicze stosowanie się do najlepszych praktyk było wartościową ceną do zapłacenia, jeśli oznaczałoby to, że mogłem stworzyć doskonalszy kod. Ale w końcu zdałem sobie sprawę, że zwięzłość może służyć jako forma abstrakcji, która może również poprawić jakość kodu - na tyle, aby uzasadniać czasem rezygnację z najlepszych praktyk.
Innymi słowy: cholera, chcę też funkcji one-liner!
Jeśli chodzi o wytyczne
Z możliwością
this
użycia neutralnych funkcji strzałek i zwięzłości, które warto realizować, oferuję następujące łagodniejsze wytyczne:Wytyczne dotyczące notacji funkcji w ES6:
this
.źródło
W prosty sposób
Kolejna instancja:
Odp .: Konsola wydrukuje 20.
Powodem jest to, że za każdym razem, gdy funkcja jest wykonywana, tworzony jest własny stos, w tym przykładzie
ex
funkcja jest wykonywana znew
operatorem, więc kontekst zostanie utworzony, a poinner
uruchomieniu JS utworzy nowy stos i wykonainner
funkcjęglobal context
chociaż istnieje kontekst lokalny.Tak więc, jeśli chcemy, aby
inner
funkcja miała kontekst lokalny, toex
znaczy musimy powiązać kontekst z funkcją wewnętrzną.Strzały rozwiązują ten problem, zamiast brać
Global context
je,local context
jeśli istnieją. Wgiven example,
to zajmienew ex()
jakthis
.Tak więc we wszystkich przypadkach, w których wiązanie jest jawne Strzałki domyślnie rozwiązują problem.
źródło
Funkcje strzałek lub Lambdas zostały wprowadzone w ES 6. Oprócz elegancji w minimalnej składni, najbardziej zauważalną różnicą funkcjonalną jest określenie zakresu
this
funkcji strzałkiOgraniczenia Funkcje strzałek jako metody na obiekcie
W przypadku,
objA.print()
gdyprint()
metoda została zdefiniowana przy użyciu funkcji regularnejfunction
, działała, rozwiązującthis
poprawnie polecenieobjA
wywołania metody, ale nie powiodła się, gdy została zdefiniowana jako=>
funkcja strzałki . Jest tak, ponieważthis
w zwykłej funkcji wywoływanej jako metoda na obiekcie (objA
) jest sam obiekt. Jednak w przypadku funkcji strzałkithis
zostaje ona powiązana leksykalniethis
z zakresem obejmującym, w którym została zdefiniowana (w naszym przypadku globalne / Window) i pozostaje niezmieniona podczas wywoływania jako metodyobjA
.Zalety funkcji strzałek w porównaniu z funkcjami zwykłymi w metodzie obiektu ALE tylko wtedy, gdy
this
oczekuje się, że zostanie ustalony i związany w definicji czasu.W przypadku
objB.print()
, gdyprint()
sposób jest zdefiniowany jako funkcja, która wywołujeconsole.log(
[$ {this.id} -> {this.name}])
asynchronicznie w postaci połączenia zwrotnego nasetTimeout
,this
rozwiązane prawidłowoobjB
, kiedy funkcja strzałka użyto wywołania zwrotnego, lecz nie kiedy oddzwonienie zostało zdefiniowane jako zwykła funkcja. Wynika to z faktu, że=>
funkcja strzałki przekazanasetTimeout(()=>..)
została zamkniętathis
leksykalnie od jej rodzica tj. wywoływanieobjB.print()
go zdefiniowało. Innymi słowy,=>
funkcja strzałki została przekazana dosetTimeout(()==>...
przypisanejobjB
jako jej,this
ponieważ wywołanieobjB.print()
this
byłoobjB
samo.Możemy łatwo użyć
Function.prototype.bind()
, aby wywołanie zwrotne zdefiniowane jako normalna funkcja działało, wiążąc je z poprawnąthis
.Jednak funkcje strzałek przydają się i są mniej podatne na błędy w przypadku wywołań zwrotnych asynchronicznych, w których znamy
this
w momencie definicji funkcji, do których się ona zwraca i powinna być ograniczona.Ograniczenie funkcji strzałek, gdy musi się to zmieniać w różnych wywołaniach
W każdej chwili potrzebujemy funkcji, którą
this
można zmienić w momencie wywołania, nie możemy używać funkcji strzałek.Żadne z powyższych nie będzie działać z funkcją strzałki
const print = () => { console.log(
[$ {this.id} -> {this.name}],);}
ponieważthis
nie można go zmienić i pozostanie związanethis
z zakresem obejmującym, w którym zostało zdefiniowane (global / Window). We wszystkich tych przykładach wywołaliśmy tę samą funkcję z różnymi obiektami (obj1
iobj2
) jeden po drugim, oba utworzone poprint()
zadeklarowaniu funkcji.Były to wymyślone przykłady, ale zastanówmy się nad kilkoma prawdziwymi przykładami. Gdybyśmy musieli napisać naszą
reduce()
metodę podobną do tej, która działaarrays
, ponownie nie możemy zdefiniować jej jako lambda, ponieważ musi ona wywnioskowaćthis
z kontekstu wywołania, tj. tablica, na której została wywołanaZ tego powodu
constructor
funkcje nigdy nie mogą być zdefiniowane jako funkcje strzałek, ponieważthis
dla funkcji konstruktora nie można ustawić w momencie deklaracji. Za każdym razem, gdy wywoływana jest funkcja konstruktoranew
słowem kluczowym, tworzony jest nowy obiekt, który następnie zostaje powiązany z tym konkretnym wywołaniem.Również gdy ramy lub systemy akceptują funkcje zwrotne, które mają być później wywoływane w kontekście dynamicznym
this
, nie możemy używać funkcji strzałek, ponieważthis
może to wymagać zmiany przy każdym wywołaniu. Taka sytuacja często występuje w przypadku programów obsługi zdarzeń DOMJest to również powód, dla którego w frameworkach takich jak Angular 2+ i Vue.js oczekuje się, że metody wiązania szablonu-komponentu będą regularnymi funkcjami / metodami, ponieważ
this
ich wywołanie jest zarządzane przez ramy dla funkcji wiązania. (Angular używa Zone.js do zarządzania kontekstem asynchronicznym do wywoływania funkcji wiązania szablonu widoku).Z drugiej strony, w React , kiedy chcemy przekazać metodę komponentu jako procedurę obsługi zdarzeń, na przykład
<input onChange={this.handleOnchange} />
powinniśmy zdefiniowaćhandleOnchanage = (event)=> {this.props.onInputChange(event.target.value);}
jako funkcję strzałki, jak przy każdym wywołaniu, chcemy, aby była to ta sama instancja komponentu, który wygenerował JSX do renderowania Element DOM.Ten artykuł jest również dostępny w mojej publikacji Medium . Jeśli podoba Ci się artile, lub masz jakiekolwiek uwagi i sugestie, proszę Clap lub pozostawić komentarze na medium .
źródło