Kodėl venkite žingsnių („++“) ir sumažinimų („-“) „JavaScript“?

Vienas iš „jslint“ įrankio patarimų:

++ ir -
++ (prieaugio) ir - (mažėjimo) operatoriai yra žinomi prisidedant prie pernelyg gudrumo skatinimo. Jie yra antra tik klaidinga architektūra teikiant virusus ir kitas grėsmes saugumui. Yra papildoma galimybė uždrausti naudoti šiuos operatorius.

Žinau, kad PHP konstruktai, tokie kaip $foo[$bar++] gali lengvai sugalvoti „vienas su vienu“ klaidas, bet negalėjau išsiaiškinti, kaip geriau valdyti kelią nei while( a < 10 ) do { a++; } while( a < 10 ) do { a++; } arba for (var i=0; i<10; i++) { } .

Ar jslint juos išryškina, nes yra keletas panašių kalbų, kurios neturi sintaksės „ ++ “ ir „ -- “, arba jas apdoroja kitaip, arba yra kitų aplinkybių, kad būtų išvengta „ ++ “ ir „ -- “, kad aš galėčiau praleisti

333
09 июня '09 в 20:02 2009-06-09 20:02 artlung yra nustatytas birželio 09 '09, 20:02 2009-06-09 20:02
@ 17 atsakymų

Mano nuomone, visada naudokite ++ ir - nepriklausomai vienoje eilutėje, kaip:

 i++; array[i] = foo; 

vietoj

 array[++i] = foo; 

Viskas, kas viršija tai, gali supainioti kai kuriuos programuotojus, ir, mano nuomone, tai tiesiog nėra verta. Ciklų atveju išimtis yra ta, kad prieaugio operatoriaus naudojimas yra idiomatinis ir todėl visada aiškus.

376
09 июня '09 в 20:30 2009-06-09 20:30 atsakymas pateikiamas cdmckay birželio 09, 09 d. 8.30 val. 2009-06-09 20:30

Atvirai kalbėjau, kad tai nepatinka. Dalis manęs nustebina, jei ji turi daugiau bendro su „JavaScript“ kodonais trūksta patirties (suvokiama ar tikra).

border=0

Galiu pamatyti, kaip kažkas „įsilaužė“ į tam tikrą pavyzdinį kodą, galėjo padaryti nekaltą klaidą c + + ir -, bet nesuprantu, kodėl patyręs specialistas juos vengtų.

233
09 июня '09 в 20:07 2009-06-09 20:07 Atsakymą davė Jon B birželio 09 d. 09:07 2009-06-09 20:07

„C“ yra istorija su tokiais dalykais kaip:

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

kopijuoti eilutę, galbūt tai yra pernelyg didelės apgaulės šaltinis.

Ir visada yra klausimas, kas

 ++i = i++; 

arba

 i = i++ + ++i; 

iš tikrųjų daro. Jis apibrėžiamas keliomis kalbomis, o kitose nėra garantijos, kas nutiks.

Šiuose pavyzdžiuose nemanau, kad yra kažkas daugiau idiomatinių nei už kilpą, kuri padidina ++ . Kai kuriais atvejais galite nutraukti naudojimąsi „foreach“ kilpa arba ciklu, kuris tikrina kitą būseną. Tačiau iškreipiant kodą, norint išvengti pakopų, yra juokinga.

68
09 июня '09 в 20:17 2009-06-09 20:17 atsakymą pateikė „ Eclipse“ birželio 09'09, 20:17 2009-06-09 20:17

Jei perskaitėte „Gerą informaciją“ „JavaScript“, pamatysite, kad „Crockford“ keitimas man „++“ kilpoje yra i + = 1 (ne man = me + 1). Ji yra gana švari ir suprantama, ir mažiau tikėtina, kad taps kažkuo „sudėtingu“.

„Crockford“ uždraudė automatinį prieaugį ir automatinį aptikimą „jsLint“. Galite pasirinkti, ar laikytis patarimo, ar ne.

Mano asmeninė taisyklė yra nieko nedaryti kartu su automatiniais žingsniais arba automatiniu aptikimu.

Iš ilgametės patirties C metu sužinojau, kad negaunu buferio perpildymo (ar masyvo indekso už ribų), jei aš ir toliau jį naudoju. Bet aš sužinojau, kad gaunu buferio perpildymą, jei pateksiu į „pernelyg sudėtingą“ praktiką daryti kitus dalykus tame pačiame pareiškime.

Taigi savo taisyklėms naudoju ++ kaip kilpos prieaugį baudai.

42
09 июня '09 в 20:34 2009-06-09 20:34 Atsakymą pateikė Nosredna birželio 09 d . 09:34 2009-06-09 20:34

Kilpoje jis yra nekenksmingas, tačiau priskyrimo ataskaitoje jis gali sukelti netikėtų rezultatų:

 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 

Tarpas tarp kintamojo ir operatoriaus taip pat gali sukelti netikėtų rezultatų:

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

Uždarant, netikėtas rezultatas gali būti problema:

 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 

Po naujos eilutės jis pradeda automatiškai įterpti kablelį:

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

Išankstinis padidėjimas / padaugėjęs supainiojimas gali sukelti papildomų klaidų, kurias sunku diagnozuoti. Laimei, jie taip pat yra visiškai nereikalingi. Yra geresnių būdų pridėti 1 prie kintamojo.

Nuorodos

25
08 янв. Atsakymą pateikė Paulas Sweatte 08 sausis 2013-01-08 21:49 '13, 21:49 PM 2013-01-08 21:49

Apsvarstykite šį 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++; 

kadangi „i ++“ duoda ženklą du kartus, išeiti (nuo „2005“ debuggerio)

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

Dabar apsvarstykite šį 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; 

Atkreipkite dėmesį, kad išėjimas yra tas pats. Dabar galite manyti, kad ++ I ir I ++ yra vienodi. Jie nėra

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

Galiausiai apsvarstykite šį 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++; 

Dabar produkcija:

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

Taigi, jie nesutampa, maišymas abu lemia mažiau intuityvų elgesį. Manau, kad ciklų c + + eilės tvarka, bet saugokitės, kai vienoje eilutėje ar toje pačioje instrukcijoje yra keli ++ simboliai

17
09 июня '09 в 20:30 2009-06-09 20:30 Atsakymą pateikė Eric birželio 09'09, 20:30, 2009-06-09 20:30

Mano nuomone, „Aiškus visada geresnis nei numanomas“. . Tam tikru momentu jums gali būti painiojamas šis operatoriaus žingsnis y+ = x++ + ++y . Geras programuotojas visada supaprastina jo kodą.

16
26 апр. Sriram atsakė balandžio 26 dieną 2011-04-26 16:26 '11, 16:26, 2011-04-26 16:26

Didėjančių ir mažėjančių operatorių „išankstinis“ ir „post“ pobūdis gali būti painus tiems, kurie nėra susipažinę su jais; kad vienas iš būdų, kaip jie gali būti sudėtingi.

16
09 июня '09 в 20:05 2009-06-09 20:05 atsakymą pateikė Paul Sonier birželio 09'09, 20:05 2009-06-09 20:05

Svarbiausia priežastis išvengti ++ arba - yra tai, kad operatoriai grąžina vertes ir tuo pačiu metu sukelia šalutinį poveikį, todėl sunku suprasti kodą.

Dėl efektyvumo aš norėčiau:

  • ++ i, kai nenaudojate grąžinimo vertės (be laikino)
  • Aš esu ++ naudodamas grįžimo vertę (be dujotiekio)

Aš esu ponas Crockford gerbėjas, bet šiuo atveju turiu nesutikti. ++i 25% mažiau teksto analizuojant nei i+=1 ir, galbūt, aiškesnis.

13
07 марта '12 в 16:51 2012-03-07 16:51 Atsakymą pateikė Hans Malherbe kovo 12 d. 12 d. 4:51 2012-03-07 16:51

Stebėjau Douglaso Crockfordo vaizdo įrašą apie tai, o jo paaiškinimas, kad neįmanoma naudoti pakopų ir dekretų, buvo toks:

  • Anksčiau ji buvo naudojama kitomis kalbomis, kad nutrauktų masyvų ribas ir sukeltų visus blogumo ir sąmoningumo būdus
  • Ką paini ir nepatyrę JS kūrėjai tiksliai nežino, ką jis daro.

Pirma, „JavaScript“ matricos turi dinamišką dydį ir todėl atleisk man, jei manęs klysta, neįmanoma nutraukti masyvo ribų ir prieiti prie duomenų, kurie neturėtų būti prieinami naudojant šį metodą „JavaScript“.

Antra, ar turėtume vengti sudėtingų dalykų, žinoma, problema nėra ta, kad turime šią priemonę, tačiau problema yra ta, kad yra kūrėjų, kurie teigia, kad veikia „JavaScript“, bet nežino, kaip šie operatoriai dirba. ? Tai gana paprasta. ++ reikšmė, duokite man dabartinę vertę ir po to, kai išraiška ją prideda, „++“ vertė padidina vertę prieš jam duodama.

Tokios išraiškos kaip ++ ++ ++ b yra paprasta kurti, jei tik prisimenate aukščiau.

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

Manau, ką tik prisimenate, kas turėtų skaityti kodą, jei turite komandą, kuri žino JS iš vidaus, tada jums nereikia nerimauti. Jei ne, komentuokite, parašykite kitaip ir tt Padarykite tai, ką reikia padaryti. Nemanau, kad augimas ir mažėjimas savaime yra blogai arba generuoja klaidas arba sukuria pažeidžiamumą, galbūt mažiau suprantamas, priklausomai nuo jūsų auditorijos.

Beje, manau, kad Douglasas Crocfordas vis tiek yra legenda, bet manau, kad jis bijo operatoriaus, kuris to nepadarė.

Aš gyvenu, kad suklydčiau ...

13
27 сент. Atsakymą pateikė Stuart Wakefield 27 rugsėjis. 2010-09-27 16:18 '10, 16:18, 2010-09-27 16:18

Kitas pavyzdys, paprastesnis nei kai kurie kiti, su paprastu pridėtinės vertės grąžinimu:

 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 

Kaip matote, grįžimo grąža neturėtų būti naudojama po prieaugio / sumažinimo, jei norite, kad šis pareiškimas paveiktų rezultatą. Tačiau grįžimas nepripažįsta po pridėtinės vertės / deklaracijos:

 function closureIncrementTest() { var x = 0; function postIncrementX() { return x++; } var y = postIncrementX(); console.log(x); // 1 } 
9
18 сент. atsakymas, kurį pateikė Evgeny Levin 18 sep. 2013-09-18 13:32 '13, 13:32 2013-09-18 13:32

Manau, kad programuotojai turėtų būti kompetentingi vartojama kalba; gerai jį naudoti; ir gerai jį naudoti. Nemanau, kad jie turėtų dirbtinai sulaužyti vartojamą kalbą. Aš kalbu iš patirties. Kartą dirbau šalia Cobol parduotuvės, kur jie nenaudojo ELSE, nes tai buvo pernelyg sudėtinga. Reductio ad absurdam.

8
27 сент. vartotojo207421 atsakymas, rugsėjo 27 d 2010-09-27 16:27 '10, 16:27, 2010-09-27 16:27

Kaip minėta kai kuriuose esamuose atsakymuose (kurie yra erzina, kad negaliu komentuoti), problema yra ta, kad x ++ ++ x vertina skirtingas vertes (prieš vs po prieaugio), kuris nėra akivaizdus ir gali būti labai painus - jei naudojama ši vertė. „cdmckay“ siūlo, kad būtų tikslinga leisti naudoti papildomą operatorių, bet tik taip, kad grąžinimo vertė nebūtų naudojama, pvz. savo eilutėje. Taip pat norėčiau įtraukti standartinį naudojimą „for loop“ (bet tik trečiame pareiškime, kuris grąžina nenaudojamą vertę). Aš negaliu galvoti apie kitą pavyzdį. Būdamas sudegintas, rekomenduoju tą patį vadovą kitoms kalboms.

Aš nesutinku su teiginiu, kad šis pernelyg didelis yra dėl to, kad daugelis JS programuotojų yra nepatyrę. Tai yra tiksli rašymo rūšis, būdinga „pernelyg protingiems“ programuotojams, ir esu tikras, kad jis yra labiau paplitęs tradicinėse kalbose ir JS kūrėjams, turintiems tokių kalbų.

2
27 янв. Atsakymas šalia Privman Jan 27 2011-01-27 09:53 '11 at 9:53 2011-01-27 09:53

Mano patirtimi, ++ me arba me ++ niekada nesukėlė painiavos, išskyrus atvejus, kai pirmą kartą sužinojote, kaip veikia operatorius. Tai svarbu daugeliui pagrindinių ciklų ir ciklų, kurie moko bet kokius mokyklų ar kolegijų kursus, mokomus kalbomis, kuriose galite naudotis operatoriumi. Asmeniškai aš atsidursiu kažką panašaus į tai, kas yra mažesnė, kad atrodytų ir skaityčiau geriau nei kažkas su c + + atskiroje eilutėje.

2
22 июня '16 в 20:26 2016-06-22 20:26 atsakymą pateikė burdzas birželio 16 d. 16, 20:26 2016-06-22 20:26

Mano, kad jie turėtų būti vengiami dviem atvejais:

1) Kai turite kintamąjį, naudojamą daugeliu eilučių, ir jūs jį padidinate / sumažinote pirmame pareiškime, kuris jį naudoja (arba paskutinį arba, dar blogiau, viduryje):

 // It 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 ) ... 

Tokiais pavyzdžiais galite lengvai praleisti, kad kintamasis automatiškai padidėtų arba sumažėtų, arba net ištrina pirmąjį teiginį. Kitaip tariant, naudokite jį tik labai trumpais blokais arba kai kintamasis rodomas bloke tik už uždarų operatorių porą.

2) Daugybiniu ++ ir - apie tą patį kintamąjį toje pačioje išraiška. Labai sunku prisiminti, kas atsitinka tokiais atvejais:

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

Egzaminai ir profesionalūs testai klausia apie tokius pavyzdžius, kaip jau minėta, ir iš tiesų atėjau šį klausimą ieškodamas dokumentacijos apie vieną iš jų, bet realiame gyvenime neturėtų būti priverstas taip galvoti apie vieną kodo eilutę.

2
30 сент. atsakymas pateikiamas zakmck 30 sep . 2016-09-30 13:40 '16 at 13:40 2016-09-30 13:40

Nežinau, ar tai buvo jo argumentavimo dalis, bet jei naudojate blogai parašytą mineralizacijos programą, ji gali pasukti x++ + y į x+++y . Bet tada vėl, blogai parašytas įrankis gali sukelti visų rūšių chaosą.

2
06 авг. atsakymą pateikė James M. 06 rugpjūtis 2009-08-06 00:46 '09 ne 0:46 2009-08-06 00:46

Ar Fortran yra C tipo kalba? Ji neturi nei nei ++, nei .... Tai rašo ciklą :

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

Indekso elementas I kiekvieną kartą didinamas naudojant kalbos taisykles naudojant ciklą. Jei norite padidinti vertę kita nei 1, skaitykite, pavyzdžiui, du kartus, sintaksę ...

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

Ar Python C patinka? Jis naudoja diapazono ir sąrašo apibrėžimus ir kitas sintakses, kad apeitų poreikį padidinti indeksą:

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

Taigi, remiantis šiuo pradiniu dviejų alternatyvų tyrimu, kalbos kūrėjai gali išvengti ++ ir - numatyti naudojimo atvejus ir teikti alternatyvią sintaksę.

Ar „Fortran“ ir „Python“ pastebimai sumažina magnetų klaidų nei procedūrinių kalbų, kuriose yra ++ ir -? Aš neturiu jokių įrodymų.

Aš tvirtinu, kad Fortranas ir Pythonas yra panašūs į C, nes niekada nesu susitikęs su nemokamu C, kuris negalėjo teisingai atspėti ketinimo neužgrobti Fortran ar Python iki 90%.

1
09 июня '09 в 20:14 2009-06-09 20:14 Atsakymą pateikė Thomas L Holaday, birželio 09'09 , 20:14, 2009-06-09 20:14