Zawsze uczono mnie, że skutki uboczne w danym if
stanie są złe. Chodzi mi o to że;
if (conditionThenHandle()) {
// do effectively nothing
}
... w przeciwieństwie do;
if (condition()) {
handle();
}
... i rozumiem to, a moi koledzy są szczęśliwi, ponieważ tego nie robię i wszyscy wracamy do domu o 17:00 w piątek i wszyscy mają wesoły weekend.
Teraz ECMAScript5 wprowadził metody takie jak every()
i some()
do Array
i uważam je za bardzo przydatne. Są czystsze niż for (;;;)
, dają ci inny zasięg i sprawiają, że element jest dostępny przez zmienną.
Jednak podczas sprawdzania poprawności danych wejściowych częściej niż nie używam every
/ some
w warunku do sprawdzania poprawności danych wejściowych, a następnie używam every
/ some
ponownie w treści, aby przekonwertować dane wejściowe na użyteczny model;
if (input.every(function (that) {
return typeof that === "number";
})) {
input.every(function (that) {
// Model.findById(that); etc
}
} else {
return;
}
... kiedy chcę to zrobić;
if (!input.every(function (that) {
var res = typeof that === "number";
if (res) {
// Model.findById(that); etc.
}
return res;
})) {
return;
}
... co daje mi skutki uboczne w if
stanie, który jest zły.
Dla porównania jest to kod wyglądający na stary for (;;;)
;
for (var i=0;i<input.length;i++) {
var curr = input[i];
if (typeof curr === "number") {
return;
}
// Model.findById(curr); etc.
}
Moje pytania to:
- Czy to zdecydowanie zła praktyka?
- Czy używam (mis | ab)
some
ievery
( powinienem używaćfor(;;;)
do tego?) - Czy istnieje lepsze podejście?
źródło
some
, chcę coś zrobić z elementem, jeśli używamevery
, chcę zrobić coś z tymi wszystkimi elementami ...some
ievery
nie pozwól mi uzyskać dostępu do tych informacji, więc albo nie mogę użyj ich, albo muszę dodać efekty uboczne.some
w moimif
stanie, aby ustalić, czy określony element w tablicy wykazuje określoną właściwość, 9/10 muszę działać na tym elemencie w moimif
ciele; teraz, ponieważsome
nie mówi mi, który z elementów wykazywał właściwość (tylko „jeden zrobił”), mogę albo użyćsome
ponownie w ciele (O (2n)), albo mogę po prostu wykonać operację wewnątrz warunku if ( co jest złe, ponieważ jest to efekt uboczny w głowie).every
oczywiście.Odpowiedzi:
Jeśli dobrze rozumiem twój punkt widzenia poprawnie, to wydaje się być mis-using lub nadużywanie
every
isome
ale to trochę nieuniknione, jeśli chcesz zmienić elementy swoich tablic bezpośrednio. Popraw mnie, jeśli się mylę, ale starasz się dowiedzieć, czy jakiś element w sekwencji ma określony warunek, a następnie zmodyfikuj te elementy. Ponadto twój kod wydaje się nakładać coś na wszystkie elementy, dopóki nie znajdziesz takiego, który nie przejdzie predykatu, i nie sądzę, że to właśnie chcesz zrobić. Tak czy inaczej.Weźmy twój pierwszy przykład (nieco zmodyfikowany)
To, co tu robisz, jest trochę sprzeczne z duchem niektórych koncepcji / Every / Map / Reduce / Filter / etc.
Every
nie ma na celu wpływania na każdy element, który jest zgodny z czymś, ale powinien być używany tylko do informowania, czy każdy element w kolekcji ma taki efekt. Jeśli chcesz zastosować funkcję do wszystkich elementów, dla których predykat ocenia się na prawdziwy, „dobrym” sposobem na to jestAlternatywnie możesz użyć
foreach
zamiast mapy, aby zmodyfikować przedmioty w miejscu.Ta sama logika dotyczy w
some
zasadzie:every
do testowania, czy wszystkie elementy tablicy przeszły jakiś test.some
do testowania, jeśli przynajmniej jeden element w tablicy przejdzie jakiś test.map
, aby powrócić nową tablicę zawierającą 1 pozycja (co jest wynikiem funkcji wyboru) dla każdego elementu w tablicy wejściowej.filter
powrotu tablicę o długości 0 <length
<initial array length
elementów, wszystkie zawarte w początkowym tablicy, a wszystkie przechodzą dostarczonego testu źródłowe.foreach
jeśli chcesz mapę, ale w miejscureduce
jeśli chcesz połączyć wyniki tablicy w wynik jednego obiektu (który może być tablicą, ale nie musi).Im częściej ich używasz (i im więcej piszesz kod LISP), tym bardziej zdajesz sobie sprawę, jak są one powiązane i w jaki sposób można nawet emulować / implementować jeden z innymi. Mocną stroną tych zapytań i naprawdę interesującą jest ich semantyka oraz to, jak naprawdę popychają cię w kierunku eliminacji szkodliwych efektów ubocznych w kodzie.
EDYCJA (w świetle komentarzy): powiedzmy, że chcesz sprawdzić, czy każdy element jest obiektem i przekonwertować go na model aplikacji, jeśli wszystkie są poprawne. Jednym ze sposobów na zrobienie tego w jednym przejściu byłoby:
W ten sposób, gdy obiekt nie przejdzie sprawdzania poprawności, nadal iterujesz przez całą tablicę, co byłoby wolniejsze niż zwykłe sprawdzanie poprawności
every
. Jednak przez większość czasu twoja tablica będzie poprawna (lub mam taką nadzieję), więc w większości przypadków wykonasz pojedyncze przejście nad tablicą i skończysz na użytecznej tablicy obiektów modelu aplikacji. Semantyka będzie przestrzegana, uniknie się skutków ubocznych i wszyscy będą szczęśliwi!Zauważ, że możesz również napisać własne zapytanie, podobne do foreach, które zastosuje funkcję do wszystkich elementów tablicy i zwróci wartość prawda / fałsz, jeśli wszystkie przejdą test predykatu. Coś jak:
Chociaż to zmodyfikowałoby tablicę na miejscu.
Mam nadzieję, że to pomaga, pisanie było bardzo fajne. Twoje zdrowie!
źródło
if (input.every())
, aby sprawdzić, czy każdy element jest obiektem (typeof el === "object && el !== null
) itp., a następnie, jeśli to się sprawdza, chcę przekonwertować każdy element na odpowiedni model aplikacji (który teraz wspominasz,map()
że mógłbym użyćinput.map(function (el) { return new Model(el); });
; ale niekoniecznie na miejscu .map()
muszę dwa razy iterować tablicę; raz, aby potwierdzić, a drugi do konwersji. Jednak stosując standardowąfor(;;;)
pętlę, mogę to zrobić za pomocą jednej iteracji, ale nie mogę znaleźć sposób, aby zastosowaćevery
,some
,map
lubfilter
w tym scenariuszu i wykonać tylko jedną przepustkę, bez niepożądanych skutków ubocznych, lub w inny sposób wprowadza złe- ćwiczyć.Efekty uboczne nie są w stanie if, są w ciele if. Określiłeś tylko, czy wykonać to ciało w rzeczywistych warunkach. W tym podejściu nie ma nic złego.
źródło
if
stanie warunkowym, a tylkoreturn
istota jest wif
ciele; oczywiście mówię o próbce kodu poprzedzonej przez „ to, co chcemy robić, to: ...if
stanie.