Uważam, że funkcja nazwanych parametrów w języku C # jest dość przydatna w niektórych przypadkach.
calculateBMI(70, height: 175);
Czego mogę użyć, jeśli chcę tego w JavaScript?
Nie chcę tego:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
Tego podejścia już użyłem. Czy jest inny sposób?
Nie przeszkadza mi używanie żadnej biblioteki.
javascript
function
optional-parameters
named-parameters
Robin Maben
źródło
źródło
Function
może zrobić istniejący w javascript.Function
w Javascript nie mogą zmienić podstawowej składni JavascriptcalculateBMI(70, /*height:*/ 175);
, (2) podanie obiektucalculateBMI(70, {height: 175})
lub (3) użycie stałejconst height = 175; calculateBMI(70, height);
.Odpowiedzi:
ES2015 i nowsze
W ES2015 destrukcji parametrów można użyć do symulacji nazwanych parametrów. Wymagałoby to od obiektu wywołującego przekazania obiektu, ale można uniknąć wszystkich kontroli wewnątrz funkcji, jeśli zostaną użyte również parametry domyślne:
ES5
Istnieje sposób, aby zbliżyć się do tego, co chcesz, ale opiera się on na
Function.prototype.toString
wynikach [ES5] , który jest w pewnym stopniu zależny od implementacji, więc może nie być kompatybilny z różnymi przeglądarkami.Chodzi o to, aby parsować nazwy parametrów z reprezentacji ciągu funkcji, aby można było powiązać właściwości obiektu z odpowiednim parametrem.
Wywołanie funkcji mogłoby wtedy wyglądać
gdzie
a
ib
są argumentami pozycyjnymi, a ostatni argument jest obiektem o nazwanych argumentach.Na przykład:
Które byś użył jako:
PRÓBNY
Istnieje kilka wad tego podejścia (zostałeś ostrzeżony!):
undefined
(która różni się od braku żadnej wartości). Oznacza to, że nie można użyćarguments.length
do sprawdzenia, ile argumentów zostało przekazanych.Zamiast mieć funkcję tworzącą opakowanie, możesz również mieć funkcję, która akceptuje funkcję i różne wartości jako argumenty, takie jak
lub nawet rozszerzyć
Function.prototype
, abyś mógł:źródło
Object.defineProperty
i ustawićenumerable
nafalse
). Zawsze należy zachować ostrożność przy rozszerzaniu obiektów rodzimych. Całe podejście wydaje się nieco zuchwałe, więc nie spodziewałbym się, że zadziała teraz i na zawsze;)undefined
vs „brak wartości” można dodać, że dokładnie tak działają domyślne wartości funkcji JS - traktując toundefined
jako wartość brakującą.Nie - podejście obiektowe jest odpowiedzią JavaScript na to. Nie ma z tym problemu, pod warunkiem, że twoja funkcja oczekuje obiektu, a nie oddzielnych parametrów.
źródło
Ta kwestia od jakiegoś czasu była moim wkurzeniem. Jestem doświadczonym programistą z wieloma językami. Jednym z moich ulubionych języków, z których miałem przyjemność korzystać, jest Python. Python obsługuje nazwane parametry bez żadnych sztuczek ... Odkąd zacząłem używać Pythona (jakiś czas temu) wszystko stało się łatwiejsze. Uważam, że każdy język powinien obsługiwać nazwane parametry, ale tak nie jest.
Wiele osób mówi, aby po prostu użyć sztuczki „Przekaż obiekt”, aby nazwać parametry.
I to działa świetnie, z wyjątkiem ..... jeśli chodzi o większość IDE dostępnych na rynku, wielu programistów korzysta z podpowiedzi typu / argumentów w naszym IDE. Osobiście używam PHP Storm (wraz z innymi IDE JetBrains, takimi jak PyCharm dla Pythona i AppCode dla Celu C)
Największy problem z użyciem sztuczki „Przekaż obiekt” polega na tym, że podczas wywoływania funkcji IDE daje ci wskazówkę dotyczącą jednego typu i to jest to ... Skąd mamy wiedzieć, jakie parametry i typy powinny wchodzić do obiekt arg1?
Więc ... sztuczka „Przekaż obiekt” nie działa dla mnie ... W rzeczywistości powoduje więcej problemów z koniecznością spojrzenia na docblock każdej funkcji, zanim dowiem się, jakich parametrów oczekuje funkcja ... Jasne, świetnie nadaje się do kiedy utrzymujesz istniejący kod, ale pisanie nowego kodu jest okropne.
Cóż, to jest technika, której używam ... Teraz mogą być z tym pewne problemy, a niektórzy programiści mogą powiedzieć mi, że robię to źle, i mam otwarty umysł, jeśli chodzi o te rzeczy ... Zawsze chętnie szukam lepszych sposobów wykonania zadania ... Jeśli więc jest problem z tą techniką, komentarze są mile widziane.
W ten sposób mam to, co najlepsze z obu światów ... nowy kod jest łatwy do napisania, ponieważ moje IDE daje mi wszystkie odpowiednie wskazówki argumentów ... A przy zachowaniu kodu później widzę nie tylko wartość przekazana do funkcji, ale także nazwa argumentu. Jedyny narzut, jaki widzę, to zadeklarowanie nazw argumentów jako zmiennych lokalnych, aby zapobiec zanieczyszczeniu globalnej przestrzeni nazw. Jasne, to trochę dodatkowego pisania, ale banalne w porównaniu do czasu potrzebnego na wyszukiwanie bloków dokumentów podczas pisania nowego kodu lub utrzymywania istniejącego kodu.
źródło
myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2');
jest to lepsze niżmyFunc(arg1='Param1', arg2='Param2');
, ponieważ nie ma szansy na oszukanie czytelnika, niż w przypadku faktycznych nazwanych argumentówJeśli chcesz wyjaśnić, jakie są parametry, zamiast wywoływania
dlaczego nie wykonać następujących czynności
pewnie, to dodatkowy wiersz kodu, ale wygrywa pod względem czytelności.
źródło
someFunction(height: 115);
ale jeśli piszeszsomeFunction(height);
, tak naprawdę ustawiasz szerokość.someFunction(width = 70, height = 115);
. Zmienne są deklarowane u góry bieżącego zakresu w generowanym kodzie JavaScript.Innym sposobem byłoby użycie atrybutów odpowiedniego obiektu, np .:
Oczywiście dla tego wymyślonego przykładu jest on nieco bez znaczenia. Ale w przypadkach, w których wygląda funkcja
to może być bardziej przydatne. Można go również połączyć z pomysłem „parametryzuj”, aby utworzyć taki obiekt z istniejącej funkcji w ogólny sposób. Oznacza to, że dla każdego parametru utworzyłby element członkowski, który może ewaluować do częściowo ocenionej wersji funkcji.
Pomysł ten jest oczywiście związany z Schönfinkeling aka Currying.
źródło
Jest inny sposób. Jeśli przekazujesz obiekt przez odniesienie, właściwości tego obiektu pojawią się w lokalnym zasięgu funkcji. Wiem, że to działa w przeglądarce Safari (nie sprawdziłem innych przeglądarek) i nie wiem, czy ta funkcja ma nazwę, ale poniższy przykład ilustruje jej użycie.
Chociaż w praktyce nie sądzę, że oferuje to jakąkolwiek wartość funkcjonalną poza techniką, której już używasz, jest nieco czystsza semantycznie. I wciąż wymaga przekazania odwołania do obiektu lub dosłowności do obiektu.
źródło
Próbując Node-6.4.0 (process.versions.v8 = „5.0.71.60”) i Node Chakracore-v7.0.0-pre8, a następnie Chrome-52 (V8 = 5.2.361.49), zauważyłem, że nazwane parametry są prawie zaimplementowano, ale ta kolejność ma nadal pierwszeństwo. Nie mogę znaleźć tego, co mówi standard ECMA.
Ale zamówienie jest wymagane !! Czy to standardowe zachowanie?
źródło
b=10
wyrażenia jest10
i to jest przekazywane do funkcji.f(bla=10)
również by działał (przypisuje 10 do zmiennej,bla
a następnie przekazuje wartość do funkcji).a
ib
zmienne w zakresie globalnym jako efekt uboczny.Wywołanie funkcji
f
z nazwanymi parametrami przekazanymi jako obiektw zasadzie nazywa swoją kompozycję, w
f(...g(o))
której używam składni rozprzestrzeniania ig
jest mapą „wiążącą” łączącą wartości obiektów z ich pozycjami parametrów.Mapa powiązań jest właśnie brakującym składnikiem, który może być reprezentowany przez tablicę jej kluczy:
Zwróć uwagę na trzy oddzielone składniki: funkcję, obiekt z nazwanymi argumentami i powiązanie. To oddzielenie pozwala na dużą elastyczność w korzystaniu z tej konstrukcji, gdzie powiązanie można dowolnie dostosować w definicji funkcji i dowolnie rozszerzyć w czasie wywołania funkcji.
Na przykład możesz chcieć skrócić
height
iwidth
jakoh
iw
wewnątrz definicji funkcji, aby była krótsza i bardziej przejrzysta, podczas gdy nadal chcesz wywoływać ją z pełnymi nazwami dla jasności:Ta elastyczność jest również bardziej użyteczna w programowaniu funkcjonalnym, w którym funkcje można dowolnie przekształcać, gubiąc oryginalne nazwy parametrów.
źródło
Pochodzące z Pythona to mnie wkurzyło. Napisałem prosty wrapper / proxy dla węzła, który akceptuje zarówno obiekty pozycyjne, jak i słowa kluczowe.
https://github.com/vinces1979/node-def/blob/master/README.md
źródło
f(x, opt)
gdzieopt
jest obiekt. To, czy pomaga to w uniknięciu błędów, czy w tworzeniu błędów (takich jak błędy ortograficzne i trudności z zapamiętywaniem nazw słów kluczowych), pozostaje pytaniem.kwargs
słownika jeden po drugim i ostatecznie podnosisz,TypeError
jeśli pozostaną nieznane klucze). Twojef(x, opt)
rozwiązanie pozwala tejf
funkcji zrobić coś takiego jak w Pythonie 2, ale sam musisz obsługiwać wszystkie wartości domyślne.f(x, opt)
to już działa, podczas gdy nie widzę, jak to pomaga odpowiedzieć na pytanie, gdzie np. Chcesz zrobić jednorequest(url)
i drugierequest({url: url})
, co nie byłoby możliwe, ustawiającurl
parametr tylko dla słowa kluczowego.Wbrew powszechnemu przekonaniu, nazwane parametry można zaimplementować w standardowym oldskulowym JavaScript (tylko dla parametrów boolowskich) za pomocą prostej, zgrabnej konwencji kodowania, jak pokazano poniżej.
Ostrzeżenia:
Kolejność argumentów musi być zachowana - ale wzorzec jest nadal użyteczny, ponieważ pokazuje, który faktyczny argument jest przeznaczony dla którego parametru formalnego, bez konieczności grepowania dla podpisu funkcji lub używania IDE.
Działa to tylko w przypadku wartości logicznych. Jestem jednak pewien, że można opracować podobny wzorzec dla innych typów przy użyciu unikalnej semantyki koercji typów JavaScript.
źródło
height
imienia bez względu na porządek param.