Po co unikać operatorów zwiększania („++”) i zmniejszania („-”) w JavaScript?

357

Jedną z porad dla narzędzia jslint jest:

++ i -
Wiadomo, że operatory ++ (inkrementacja) i - (dekrementacja) przyczyniają się do złego kodu, zachęcając do nadmiernej podstępności. Zajmują drugie miejsce po wadliwej architekturze, umożliwiając wirusom i innym zagrożeniom bezpieczeństwa. Istnieje opcja plusplus, która zabrania korzystania z tych operatorów.

Wiem, że PHP buduje jak $foo[$bar++]ma może łatwo prowadzić do błędów off-by-one, ale nie mogłem wymyślić lepszego sposobu kontrolowania pętlę, niż miało to while( a < 10 ) do { /* foo */ a++; }albo for (var i=0; i<10; i++) { /* foo */ }.

Czy jslint je uwypukla, ponieważ istnieją podobne języki, w których brakuje składni „ ++” i „ --” lub obsługują je inaczej, czy też istnieją inne uzasadnienia dla uniknięcia „ ++” i „ --”, których mogłem pominąć?

artlung
źródło
59
Dlatego należy wykonać tablicę [indeks = indeks + 1] zamiast tablicy [++ indeks] (jeśli pierwsza jest nawet dozwolona!). Co za hooey.
Lawrence Dol
34
Nie widziałem Crockforda indeks = indeks + 1. Widziałem, jak robi indeks + = 1. Myślę, że to rozsądna alternatywa. I to jest miłe, gdy chcesz zmienić krok na coś innego niż 1.
Nosredna
124
Osobiście nie jestem wielkim fanem Crockford. Wydaje się, że uważa wszystko, co kiedykolwiek spowodowało błąd w jego kodzie, za złe.
Paolo Bergantino,
38
W JavaScript powinieneś traktować każdy błąd jako coś złego, ponieważ nie ma oficjalnej dokumentacji, nie ma dostawcy certyfikatu ani nie uczysz się poprawnie JS na uniwersytecie. Crockford i Firebug wypełniły te dziury w edukacji JavaScript.
stevek
40
++nie powoduje błędów. Używanie ++„podstępnych” sposobów może prowadzić do błędów, zwłaszcza jeśli więcej niż jedna osoba utrzymuje bazę kodu, ale to nie jest problem z operatorem, to problem z programistą. Nie uczyłem się JS na uniwersytecie (ponieważ jeszcze nie istniał), ale co z tego? Zrobiłem C, który oczywiście miał ++pierwszy, ale to też dostaje „co z tego?” Nie poszedłem na uniwersytet, aby uczyć się określonego języka, poszedłem nauczyć się dobrych praktyk programistycznych, które mogę zastosować do dowolnego języka.
nnnnnn

Odpowiedzi:

408

Moim zdaniem zawsze używam ++ i - same w jednym wierszu, jak w:

i++;
array[i] = foo;

zamiast

array[++i] = foo;

Cokolwiek poza tym może być mylące dla niektórych programistów i po prostu nie jest tego warte. Pętle są wyjątkiem, ponieważ użycie operatora inkrementacji jest idiomatyczne, a zatem zawsze jasne.

cdmckay
źródło
3
Tak, ja też to robię. Trudno się pomylić i łatwiej innym ludziom dowiedzieć się, co robisz.
Nosredna
65
Wydaje się, że to sedno problemu i moje zamieszanie. Używany samodzielnie, i ++; jest krystalicznie czysty. W momencie, gdy dodajesz inny kod wokół tego podstawowego wyrażenia, czytelność i przejrzystość zaczynają cierpieć.
artlung
2
Zgadzam się, ale nie jest to związane tylko z JavaScriptem
Tobias
5
Nie mówisz, czy piszesz C czy C ++. Prawdopodobnie powinieneś użyć operatora inkrementacji prefiksu w C ++, na wypadek gdyby izmienna później stała się klasą złożoną, w którym to przypadku niepotrzebnie tworzysz obiekt tymczasowy. Uważam jednak, że operator Postfiksa jest bardziej estetyczny.
mc0e,
2
Wolę wersję 1-liniową. Przypomina operację na stosie. push to tablica [++ i] = foo, pop to bar = tablica [i--]. (Ale w przypadku tablic opartych na 0 tablica [i ++] = foo i bar = tablica [- i] wyglądają jeszcze lepiej). Kolejna rzecz, nie znosiłbym tego, gdyby ktoś dodał dodatkowy kod między i ++; i tablica [i] = foo ;.
Florian F
257

Jestem szczerze zdezorientowany tą radą. Część mnie zastanawia się, czy to ma więcej wspólnego z brakiem doświadczenia (postrzeganego lub faktycznego) z koderami javascript.

Widzę, jak ktoś, kto po prostu „hakuje” jakiś przykładowy kod, może popełnić niewinny błąd w ++ i - ale nie rozumiem, dlaczego doświadczony profesjonalista miałby go unikać.

Jon B.
źródło
7
Dobra uwaga Jon B. Właśnie dlatego tak mnie to niepokoi. Crockford jest programistą zawodowym (wartym dziesięcioleci), znającym wiele języków przez dziesięciolecia i pracującym z JavaScript w zasadzie od samego początku. Nie sądzę, by jego rada pochodziła od „Jestem leniwym i nieuważnym niedoświadczonym hakerem” - dlatego staram się zrozumieć, skąd się bierze.
artlung
14
@artlung Być może chodzi raczej o „Leniwego i nieuważnego niedoświadczonego hakera” prawdopodobnie zepsuje ten kod i nie chcę go mylić.
Chris Cudmore,
9
Całkowicie nie zgadzam się z twoją odpowiedzią. Moim zdaniem nie chodzi o „Czy mam dość doświadczenia, aby z niego korzystać?” - ale „Czy jaśniej czy nie?” Jeśli wewnątrz pętli for lub sam, jest krystalicznie czysta - wszyscy zrozumieją to bez szkody. Problem pojawia się, gdy ++bardziej skomplikowane wyrażenie w ++ ++ różni się od x ++, co powoduje, że coś nie jest łatwe do odczytania. Pomysł Crockforda nie dotyczy „czy mogę to zrobić?” chodzi o „jak uniknąć błędów?”
ArtoAle,
1
Indywidualne preferencje, w którym momencie jasność jest dla Ciebie ważniejsza niż zwartość. Wykracza to poza doświadczenie na tyle, aby zrozumieć kod. Zobacz inne odpowiedzi na przykłady, w których jest więcej kłopotów niż jest to warte.
Frug
1
W pełni się zgadzam. Po co sobie przeszkadzać, nie używając części języka? Znajduję dobre powody, aby stosować zarówno przyrosty, jak i przyrosty. Dla mnie taka linia jest jasna i zwięzła ... if (--imagesLoading === 0) start (); Jeśli uważasz, że Twój kod jest niejasny, użyj komentarzy!
xtempore,
69

W C jest historia robienia takich rzeczy jak:

while (*a++ = *b++);

aby skopiować ciąg znaków, być może jest to źródło nadmiernej sztuczki, o której mówi.

I zawsze jest pytanie o co

++i = i++;

lub

i = i++ + ++i;

faktycznie tak. Jest zdefiniowany w niektórych językach, aw innych nie ma gwarancji, co się stanie.

Pomijając te przykłady, nie sądzę, aby istniało coś bardziej idiomatycznego niż pętla for, która służy ++do zwiększania. W niektórych przypadkach można było uniknąć pętli foreach lub pętli while, która sprawdzała inne warunki. Ale zniekształcanie kodu w celu uniknięcia inkrementacji jest niedorzeczne.

Zaćmienie
źródło
104
i = i ++ + ++ i; sprawiło, że trochę bolały mnie oczy - :)
Hugoware
3
Moje też. Nawet jeśli nie były to wszystkie te same zmienne, powiedzmy, że miałem x = a ++ + ++ b; - ta kombinacja sprawia, że ​​x, aib są trudniejsze do trzymania w mojej głowie. teraz, jeśli każdy z nich byłby osobnymi instrukcjami w osobnych wierszach, jak w - a ++; ++ b; x = a + b; łatwiej byłoby to zrozumieć na pierwszy rzut oka.
artlung
10
Niestety, (a ++; b ++; x = a = b) nie jest taką samą wartością jak (a ++ + ++ b).
Thomas L Holaday
8
@Marius: x = a+++b-> x = (a++)+b-> x = a + b; a++. Tokeniser jest chciwy.
Callum Rogers,
14
Aby zwiększyć bezpieczeństwo pracy, usuń spacje w ostatnim przykładzie.
mc0e,
48

Jeśli czytasz JavaScript The Good Parts, zobaczysz, że zamiennik Crockforda dla i ++ w pętli for to i + = 1 (nie i = i + 1). Jest to dość czyste i czytelne i jest mniej prawdopodobne, że zamieni się w coś „podstępnego”.

Crockford ustawił opcję niedozwolonej autoakrementacji i autodekrecji jako opcję w jsLint. Ty decydujesz, czy zastosować się do porady, czy nie.

Moją osobistą zasadą jest, aby nie robić niczego w połączeniu z automatycznym zwiększaniem lub automatycznym zwiększaniem.

Nauczyłem się z wieloletniego doświadczenia w C, że nie dostaję przekroczeń bufora (lub indeksu tablicy poza granicami), jeśli nadal używam tego prostego. Ale odkryłem, że dostaję przepełnienia bufora, jeśli wpadnę w „nadmiernie podchwytliwą” praktykę robienia innych rzeczy w tym samym stwierdzeniu.

Tak więc, zgodnie z moimi własnymi regułami, użycie i ++ jako przyrostu w pętli for jest w porządku.

Nosredna
źródło
Doskonała uwaga, że ​​opcja „plusplus” jest właśnie taką opcją. W oparciu o twoje i inne odpowiedzi wydaje mi się, że mam wrażenie, że ++ sam w sobie lub pętla for nie są same w sobie mylące. W momencie, gdy połączysz ++ w innej instrukcji, instrukcja staje się trudniejsza do odczytania i zrozumienia w kontekście.
artlung
6
wszyscy dostają przepełnienia bufora. Nawet OpenSSH z ich otwartym oprogramowaniem i wieloma komisjami zmian
Eric
11
@Eric Powracając do twojego pięcioletniego komentarza: och, jak masz rację!
wchargin
27

W pętli jest nieszkodliwy, ale w instrukcji przypisania może prowadzić do nieoczekiwanych rezultatów:

var x = 5;
var y = x++; // y is now 5 and x is 6
var z = ++x; // z is now 7 and x is 7

Biała spacja między zmienną a operatorem może również prowadzić do nieoczekiwanych wyników:

a = b = c = 1; a ++ ; b -- ; c; console.log('a:', a, 'b:', b, 'c:', c)

W zamknięciu nieoczekiwane wyniki mogą również stanowić problem:

var foobar = function(i){var count = count || i; return function(){return count++;}}

baz = foobar(1);
baz(); //1
baz(); //2


var alphabeta = function(i){var count = count || i; return function(){return ++count;}}

omega = alphabeta(1);
omega(); //2
omega(); //3

I uruchamia automatyczne wstawianie średnika po nowej linii:

var foo = 1, bar = 2, baz = 3, alpha = 4, beta = 5, delta = alpha
++beta; //delta is 4, alpha is 4, beta is 6

Zamieszanie poprzedzające zwiększenie / dodatkowe może powodować powstawanie błędów, które są niezwykle trudne do zdiagnozowania. Na szczęście są one również całkowicie niepotrzebne. Istnieją lepsze sposoby dodania 1 do zmiennej.

Bibliografia

Paul Sweatte
źródło
13
Ale nie są „nieoczekiwane”, jeśli rozumiesz operatora. To tak, jakby nigdy nie używać, ==ponieważ nie rozumiesz różnicy między ==i ===.
greg84,
1
Dokładnie. Jest pytanie C #, które obala fałszywe założenia.
Paul Sweatte,
Myślę, że Crockford ma na myśli to, że większość programistów nie w pełni „rozumie operatora”, nawet jeśli tak myślą; stąd ich użycie jest niebezpieczne, ponieważ potencjał nieporozumień jest wysoki. Zobacz komentarz @ Paula na temat fałszywych założeń, który wzmacnia argument, że ludzie na ogół źle rozumieją, jak faktycznie działają operatory prefiksów i postfiksów. To powiedziawszy, przyznaję, że lubię ich używać, ale ze względu na innych staram się ograniczać ich użycie do przypadków idiomatycznych (patrz odpowiedź cdmckay ).
gfullam
Twój link do białych znaków wydaje się być uszkodzony.
Ruslan
Co jest podstępnego w twoim przykładzie „białych znaków”? Otrzymuję prosty wynik a: 2 b: 0 c: 1. Nie widzę też nic dziwnego ani nieoczekiwanego w pierwszym przykładzie („instrukcja przypisania”).
Ken Williams,
17

Rozważ następujący kod

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[i++] = i++;
    a[i++] = i++;
    a[i++] = i++;

ponieważ i ++ jest oceniany dwukrotnie, wyjście to (z debuggera vs2005)

    [0] 0   int
    [1] 0   int
    [2] 2   int
    [3] 0   int
    [4] 4   int

Teraz rozważ następujący kod:

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[++i] = ++i;
    a[++i] = ++i;
    a[++i] = ++i;

Zauważ, że wynik jest taki sam. Teraz możesz pomyśleć, że ++ i i ++ są takie same. Oni nie są

    [0] 0   int
    [1] 0   int
    [2] 2   int
    [3] 0   int
    [4] 4   int

Na koniec rozważ ten kod

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[++i] = i++;
    a[++i] = i++;
    a[++i] = i++;

Dane wyjściowe są teraz:

    [0] 0   int
    [1] 1   int
    [2] 0   int
    [3] 3   int
    [4] 0   int
    [5] 5   int

Więc nie są takie same, mieszanie obu powoduje nie tak intuicyjne zachowanie. Myślę, że pętle są w porządku z ++, ale uważaj, gdy masz wiele symboli ++ w tej samej linii lub tej samej instrukcji

Eric
źródło
3
Dzięki za wykonanie tego eksperymentu. Szczególnie „prosty” kod, ale mój mózg ma trudności z jego bardzo szybkim utrzymaniem. Zdecydowanie należy do kategorii „podstępnej”.
artlung
28
Zatrzymałem się po pierwszym przykładzie. Powiedziałeś „Rozważ następujący kod”. Nie, nikt nie pisze tego kodu. To idiota, który pisze, że jest wadliwy, a nie konstrukcja językowa.
Sam Harwell,
4
Pokazałeś, że dwa różne fragmenty kodu generują różne dane wyjściowe, a to dowodzi, że jest zły?
nickf
7
wniosek jest następujący: „uważaj, gdy masz wiele symboli ++ w tej samej linii lub tej samej instrukcji”. Nie sądzę, żebyś to przeczytał
Eric,
1
„ponieważ i ++ jest oceniany dwukrotnie” - źle! Dwukrotne zmodyfikowanie zmiennej między punktami sekwencji, a także jej użycie jest niepoprawne w C ++ i prowadzi do niezdefiniowanego zachowania. Kompilator może więc robić, co chce. Przedstawione tutaj wyniki są przypadkowe w przypadku implementacji kompilatora.
tbleher
16

„Przed” i „po” charakter operatorów zwiększania i zmniejszania może być mylący dla tych, którzy ich nie znają; to jeden ze sposobów, w jaki mogą być podstępni.

Paul Sonier
źródło
29
Zgoda; doświadczonego profesjonalisty nie należy jednak mylić.
Nate
1
Myślę, że jest to podobne do wskazówek, aby uniknąć uczynienia wszystkiego statycznym lub globalnym. Nie ma w tym nic złego jako konstruktu programistycznego, ale ignoranckie nadużywanie może prowadzić do złego kodu.
Joel Martinez
6
Pytanie nie polega na tym, czy dobry programista może „przebrnąć przez logikę” - dobry kod idealnie nie wymaga żadnej pracy do zrozumienia. Myślę, że McWafflestix ma na myśli to, że nie powinieneś pisać kodu, który po krótkiej inspekcji może prowadzić do dodawania błędów w ciągu dwóch tygodni lub dwóch lat. Wiem, że byłem winny dodawania kodu do procedury, której nie do końca rozumiałem :)
Mike
1
@ Mike: tak, zauważ, jak nie określiłem, czy operatorzy mogą być podstępni dla pierwotnego autora kodu lub późniejszych opiekunów. Zasadniczo staramy się założyć, że oryginalni koderzy nie używają konstrukcji, których nie znają / nie czują się komfortowo (niestety, często jest to błędne założenie); jednak ta znajomość z pewnością nie rozciąga się na opiekunów (i, jak podano nawiasowo powyżej, może nawet nie obejmować autora oryginału).
Paul Sonier,
Próbuję napisać kod, aby inni programiści mogli go przeczytać, ale nie próbuję go napisać dla początkujących.
Łukasz H
16

Moim zdaniem „Jawne jest zawsze lepsze niż niejawne”. Ponieważ w pewnym momencie możesz pomylić się z tym oświadczeniem o przyrostach y+ = x++ + ++y. Dobry programista zawsze czyni swój kod bardziej czytelnym.

Sriram
źródło
1
W x ++ lub ++ y nie ma nic ukrytego.
Florian F,
1
Ta czytelna kwestia kodu jest trudna ... Myślę, że istnieje podstawowa podstawa tego, jak prosty musi być twój kod, a my - jako społeczność - musimy się trochę rozwijać i być w stanie odczytać to, czego teraz nie można odczytać, takie jak jednowierszowe z zagnieżdżonymi trójskładnikami, aby umożliwić więcej rzeczy.
Hamza Ouaghad
14

Najważniejszym uzasadnieniem unikania ++ lub - jest to, że operatorzy zwracają wartości i powodują skutki uboczne w tym samym czasie, co utrudnia rozumowanie na temat kodu.

Ze względu na wydajność wolę:

  • ++ i, gdy nie używasz wartości zwracanej (bez tymczasowej)
  • i ++ przy użyciu wartości zwracanej (brak przeciągnięcia rurociągu)

Jestem fanem pana Crockforda, ale w tym przypadku muszę się nie zgodzić. ++ijest o 25% mniej tekstu do przeanalizowania niż i+=1 i jest prawdopodobnie wyraźniejszy.

Hans Malherbe
źródło
13

Oglądałem film Douglasa Crockforda na ten temat, a jego wyjaśnienie, że nie używa przyrostu i zmniejszenia, jest takie

  1. W przeszłości był używany w innych językach, aby przełamać granice tablic i spowodować wszelkie obyczaje i zło
  2. Że jest bardziej mylące i niedoświadczeni programiści JS nie wiedzą dokładnie, co robi.

Po pierwsze, tablice w JavaScript mają dynamiczny rozmiar, więc wybacz mi, jeśli się mylę, nie jest możliwe przełamanie granic tablicy i dostęp do danych, do których nie można uzyskać dostępu za pomocą tej metody w JavaScript.

Po drugie, czy powinniśmy unikać rzeczy, które są skomplikowane, z pewnością problemem nie jest to, że mamy tę funkcję, ale problemem jest to, że istnieją programiści, którzy twierdzą, że robią JavaScript, ale nie wiedzą, jak działają ci operatorzy? To jest dość proste. wartość ++, podaj mi bieżącą wartość, a po wyrażeniu dodaj do niej jedną wartość ++, zwiększ wartość przed jej podaniem.

Wyrażenia takie jak ++ + ++ b są łatwe do wypracowania, jeśli tylko pamiętasz powyższe.

var a = 1, b = 1, c;
c = a ++ + ++ b;
// c = 1 + 2 = 3; 
// a = 2 (equals two after the expression is finished);
// b = 2;

Przypuszczam, że właśnie pamiętasz, kto musi przeczytać kod, jeśli masz zespół, który zna JS na wylot, nie musisz się martwić. Jeśli nie, to skomentuj to, napisz inaczej, itd. Rób to, co musisz zrobić. Nie sądzę, aby inkrementy i dekrementacje były z natury złe, generowały błędy lub stwarzały luki, być może były po prostu mniej czytelne w zależności od odbiorców.

Przy okazji, myślę, że Douglas Crockford i tak jest legendą, ale myślę, że spowodował wiele strachu przed operatorem, który na to nie zasłużył.

Jednak żyję, aby udowodnić, że się mylę ...

Stuart Wakefield
źródło
10

Kolejny przykład, prostszy niż niektóre inne z prostym zwrotem wartości przyrostowej:

function testIncrement1(x) {
    return x++;
}

function testIncrement2(x) {
    return ++x;
}

function testIncrement3(x) {
    return x += 1;
}

console.log(testIncrement1(0)); // 0
console.log(testIncrement2(0)); // 1
console.log(testIncrement3(0)); // 1

Jak widać, w deklaracji return nie należy stosować postkrementacji / dekrementacji, jeśli chcesz, aby ten operator wpływał na wynik. Ale return nie „łapie” operatorów po zwiększeniu / zmniejszeniu:

function closureIncrementTest() {
    var x = 0;

    function postIncrementX() {
        return x++;
    }

    var y = postIncrementX();

    console.log(x); // 1
}
Evgeny Levin
źródło
Tylko jedna z twoich funkcji odbiera x jako parametr
Calimero100582
8

Myślę, że programiści powinni być biegli w języku, którego używają; używaj go wyraźnie; i używaj go dobrze. I nie myśleć sztucznie powinny one sparaliżować język, którego używają. Mówię z doświadczenia. Kiedyś dosłownie pracowałam obok sklepu Cobola, w którym nie używali ELSE „ponieważ było to zbyt skomplikowane”. Reductio ad absurdam.

Markiz Lorne
źródło
@downvoter Fascinating. Nie uważasz, że programiści powinni być biegli w języku? Myślisz, że powinni sztucznie okaleczyć język? Który to jest? Nie ma tu trzeciego wyboru.
Markiz Lorne
1
a opinia o tym przykładzie COBOL sprawia, że ​​jeszcze bardziej cieszę się, że COBOL w większości wymarł, zanim zacząłem kodować
Mark K Cowan
1
@MarkCowan Nie rozumiem dlaczego. Chodzi mi o arbitralne ograniczenie, a nie o język. Anegdota nie wskazuje na nic złego w Cobolu. To, co musiało umrzeć, to sklep programistyczny i tak się stało. Odwiedź wnętrzności dowolnego dużego banku, a przekonasz się, że Cobol żyje i ma się dobrze.
Markiz Lorne
2

Jak wspomniano w niektórych z istniejących odpowiedzi (których irytująco nie jestem w stanie skomentować), problem polega na tym, że x ++ ++ x ocenia na różne wartości (przed vs po przyrostie), co nie jest oczywiste i może być bardzo mylące - gdyby ta wartość zostanie użyta. cdmckay sugeruje dość mądrze zezwolić na użycie operatora inkrementacji, ale tylko w taki sposób, aby zwrócona wartość nie była używana, np. we własnej linii. Chciałbym również włączyć standardowe użycie w pętli for (ale tylko w trzeciej instrukcji, której zwracana wartość nie jest używana). Nie mogę wymyślić innego przykładu. Ponieważ sam zostałem „spalony”, poleciłbym tę samą wskazówkę także w innych językach.

Nie zgadzam się z twierdzeniem, że ta nadmierna surowość wynika z niedoświadczenia wielu programistów JS. Jest to dokładnie rodzaj pisania typowy dla „zbyt sprytnych” programistów, i jestem pewien, że jest on znacznie bardziej powszechny w bardziej tradycyjnych językach oraz z programistami JS, którzy mają doświadczenie w takich językach.

Blisko Privman
źródło
1
Dziękuję za odpowiedź. Aby móc komentować, musisz mieć reputację 50 lub lepszą. Zobacz: stackoverflow.com/faq
artlung
1
@artlung: Jestem tego świadomy i uzasadnienie. Właśnie mówiłem, że to denerwujące :)
Blisko Privman
2

Z mojego doświadczenia wynika, że ​​++ i lub i ++ nigdy nie powodowały zamieszania, chyba że po raz pierwszy dowiedziały się, jak działa operator. Jest niezbędny w przypadku najbardziej podstawowych pętli, a jednocześnie pętli prowadzonych przez dowolne liceum lub na studiach prowadzonych w językach, w których można używać operatora. Osobiście uważam, że robię coś takiego, co jest poniżej, aby wyglądać i czytać lepiej niż coś z ++ w osobnej linii.

while ( a < 10 ){
    array[a++] = val
}

Ostatecznie jest to preferencja stylu i nic więcej, ważniejsze jest to, że robiąc to w kodzie, zachowujesz spójność, aby inni pracujący nad tym samym kodem mogli śledzić i nie musieli przetwarzać tej samej funkcjonalności na różne sposoby .

Ponadto Crockford wydaje się używać i- = 1, co wydaje mi się trudniejsze do odczytania niż - i lub i--

burdz
źródło
2

Moim 2 centami jest to, że należy ich unikać w dwóch przypadkach:

1) Gdy masz zmienną, która jest używana w wielu wierszach i zwiększasz / zmniejszasz ją w pierwszym wyrażeniu, które jej używa (lub ostatnim, a nawet gorzej, w środku):

// It's Java, but applies to Js too
vi = list.get ( ++i );
vi1 = list.get ( i + 1 )
out.println ( "Processing values: " + vi + ", " + vi1 )
if ( i < list.size () - 1 ) ...

W takich przykładach można łatwo przeoczyć, że zmienna jest automatycznie zwiększana / zmniejszana, a nawet usunąć pierwszą instrukcję. Innymi słowy, używaj go tylko w bardzo krótkich blokach lub tam, gdzie zmienna pojawia się w bloku tylko na kilku bliskich instrukcjach.

2) W przypadku wielu ++ i - o tej samej zmiennej w tej samej instrukcji. Bardzo trudno jest zapamiętać, co dzieje się w takich przypadkach:

result = ( ++x - --x ) * x++;

Egzaminy i profesjonalne testy pytają o przykłady takie jak powyżej i rzeczywiście natknąłem się na to pytanie, szukając dokumentacji na temat jednego z nich, ale w rzeczywistości nie należy zmuszać do myślenia o jednej linii kodu.

zakmck
źródło
1

Czy Fortran jest językiem podobnym do C? Nie ma ani ++, ani -. Oto jak piszesz pętlę :

     integer i, n, sum

      sum = 0
      do 10 i = 1, n
         sum = sum + i
         write(*,*) 'i =', i
         write(*,*) 'sum =', sum
  10  continue

Element indeksu i jest zwiększany przez reguły językowe za każdym razem przez pętlę. Jeśli chcesz zwiększyć o coś innego niż 1, na przykład policz wstecz o dwa, składnia to ...

      integer i

      do 20 i = 10, 1, -2
         write(*,*) 'i =', i
  20  continue

Czy Python C jest podobny? Wykorzystuje wyrażenia zakresu i list oraz inne składnie, aby ominąć potrzebę zwiększania indeksu:

print range(10,1,-2) # prints [10,8.6.4.2]
[x*x for x in range(1,10)] # returns [1,4,9,16 ... ]

Opierając się na tym szczątkowym badaniu dokładnie dwóch alternatyw, projektanci języków mogą uniknąć ++ i - przewidując przypadki użycia i zapewniając alternatywną składnię.

Czy Fortran i Python są w mniejszym stopniu magnesem błędów niż języki proceduralne, które mają ++ i -? Nie mam dowodów.

Twierdzę, że Fortran i Python są podobne do C, ponieważ nigdy nie spotkałem osoby biegłej w C, która nie mogłaby z 90% dokładnością odgadnąć poprawnie zamiaru nie zaciemnienia Fortrana lub Pythona.

Thomas L. Holaday
źródło
1
Tak, IFortran pochodzi z lat 50., podczas gdy C pochodzi z lat 70., więc może nie, żeby Fortran był podobny do C. Ciekawy jest przykład Pythona pozbawionego czegoś takiego jak operator plusplus. Iterowanie po strukturach danych jest łatwiejsze w Pythonie, ponieważ Python jest „inaczej” obiektowym JavaScript. Być może rada Crockforda dotyczy używania więcej iteracyjnej składni podobnej do OO.
artlung