piszesz JavaScript i nagle uświadamiasz sobie z przerażeniem i przerażeniem, że napisałeś ogromną funkcję. To przytrafiło się najlepszym z nas. Teraz przychodzi niemal niepowstrzymana chęć oddzielenia funkcji na mniejsze kawałki.
Duże funkcje oznaczają wiele obowiązków w jednym miejscu i ewentualnie zapach kodu, więc sam w sobie jest to dobry pomysł. Ale chcesz rozbić funkcję w taki sposób, aby nie straciła znaczenia ani kontekstu. Aby to zrobić, musisz pomyśleć o łańcuchach metod-zwanych również łańcuchami funkcji. Ten artykuł wyjaśni, co mam na myśli.
wymagania wstępne
zanim zaczniemy, oto kilka pojęć JavaScript, które musisz już znać:
- funkcje strzałek
- metody tablicowe
- funkcje asynchroniczne
większość doświadczonych programistów ma pewne doświadczenie z metodami Array
, takimi jak mapowanie, zmniejszanie i filtrowanie. Prawdopodobnie już natknąłeś się na coś takiego:
const food = ;// This type of usage is very commonfood .map(item => item.type) .reduce((result, fruit) => { result.push(fruit); return ; }, );// result:
łańcuchowanie metod ma miejsce, gdy chcesz wywołać wiele funkcji przy użyciu tego samego obiektu i jego odniesienia. W powyższym przykładzie metoda array map
zwraca Array
, która ma ogromną liczbę metod.
ponieważ zwracasz referencję wskazującą na Array
, będziesz mieć dostęp do wszystkich właściwości Array
. To ta sama zasada, której używasz do tworzenia własnych łańcuchów.
lepsze zrozumienie tego
Nie omówię wszystkich niuansów this
, ale dobrze jest zrozumieć, dlaczego this
działa tak, jak działa. Bez względu na to, jak doświadczony jesteś, słowo kluczowe może być trudne do zrozumienia. Często jest to powód, dla którego rzeczy nie działają tak, jak tego oczekujesz.
oto jego sedno: this
zawsze wskazuje na bieżącą scope
lub instancję, z której jest wywołana. Przykład:
const dog = { is: null, log: () => console.log(this.is), bark() { this.is = "woofing"; this.log(); return this; }, walk() { this.is = "walking"; this.log(); return this; }, eat() { this.is = "eating"; this.log(); return this; }};dog .bark() .eat() .walk();
kiedy piszesz taką funkcję (bez kalambura), możesz chcieć łańcuchować metody, które są powiązane z obiektem. Obiekt dog
posiada 3 metody: walk
, bark
oraz eat
. Za każdym razem, gdy wywołuję którąkolwiek z jego funkcji, konsola powinna pokazywać przedstawienie tego, co pies robi dokładnie w tym momencie.
ale jest z tym problem. Jeśli uruchomisz go w przeglądarce, zdasz sobie sprawę, że nie działa zgodnie z oczekiwaniami. Dzieje się tak dlatego, że funkcje strzałek używają leksykalnego zakresu, gdzie this
odnosi się do otaczającego go zakresu – w tym przypadku window
, a nie do samego obiektu.
aby to rozwiązać, powinniśmy użyć anonimowego wywołania funkcji reprezentującej właściwość log
:
// instead of this: log: () => console.log(this.is),// use this: log() { console.log(this.is); }
teraz zasięg psa this
będzie dostępny wewnątrz funkcji.
używając klasy
możesz osiągnąć ten sam wynik używając klas:
class Dog { is = null; log() { console.log(this.is); } bark() { this.is = "woofing"; this.log(); return this; } walk() { this.is = "walking"; this.log(); return this; } eat() { this.is = "eating"; this.log(); return this; }}const dog = new Dog();dog .bark() .eat() .walk();
używanie Prototype
jeśli musisz użyć prototype, zrób to w ten sposób:
function Dog() {}Dog.prototype.is = null;Dog.prototype.log = function() { console.log(this.is);};Dog.prototype.bark = function() { this.is = "woofing"; this.log(); return this;};Dog.prototype.walk = function() { this.is = "walking"; this.log(); return this;};Dog.prototype.eat = function() { this.is = "eating"; this.log(); return this;};const dog = new Dog();dog .bark() .eat() .walk();
Co Z Funkcjami Asynchronicznymi?
async
funkcje są syntetycznym cukrem dla obietnic i generatorów. Kiedy deklarujesz funkcję async
, wiesz, że zwróci ona obietnicę. Z tego powodu będziesz mieć również dostęp do wszystkich metod obietnicy.
const requests = { user: null, action: null, log(something) { console.log(this); }, async getUser() { this.user = await new Promise(resolve => { setTimeout(() => { resolve("Douglas Pires"); }, 1000); }); this.log("user"); return this; }, async registerAction() { this.action = await new Promise(resolve => { setTimeout(() => { resolve("programming stuff"); }, 1000); }); this.log("action"); return this; }};requests.getUser().then(() => requests.registerAction());
jednak nie jest to dobry pomysł, aby połączyć kilka obietnic razem. Zalecam użycie zamiast tego kilku słów kluczowych await
. Jest to łatwiejsze i sprawi, że Twój kod będzie znacznie bardziej czytelny.
await requests.getUser(); // Douglas Piresawait requests.registerAction(); // programming
i będziesz miał dostęp do tych samych właściwości tutaj:
console.log(requests.user); // Douglas Piresconsole.log(requests.action); // programming
Podsumowując
funkcje łańcuchowe są przydatne, gdy trzeba manipulować obiektem. Jest to również praktyczny sposób na poprawę czytelności kodu. Jednak, jak widać powyżej, należy mądrze łańcuch.
w tym artykule omówiliśmy funkcje this
, klasy, prototypy i async
w kontekście łańcuchowania metod JavaScript. Mam nadzieję, że wybrałeś kilka przydatnych wskazówek i jesteś teraz lepiej poinformowany na ten temat. Możesz znaleźć moje repozytorium z całym kodem na łańcuchu metod JavaScript tutaj. Do zobaczenia w następnym poście!
podobało ci się czytanie tego artykułu? Zachęcamy do udostępniania w mediach społecznościowych za pomocą poniższych przycisków. Alternatywnie, pisałem również o tym, jak można zbudować generator palety kolorów za pomocą Nuxt i Vuetify. Sprawdź to!