Javascript funkcijų tvarka: kodėl tai svarbu?

Originalus klausimas:

„JSHint“ skundžiasi, kai mano „JavaScript“ skambina toliau apibrėžta funkcija, nei skambinama į jį. Tačiau mano puslapis skirtas žaidimui, o jokios funkcijos nebus iškviestos, kol visa tai nebus parsisiunčiama. Taigi, kodėl mano kode rodomos užsakymo funkcijos?

EDIT: Manau, kad suradau atsakymą.

http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

Aš ištvirkauju. Atrodo, kad turiu praleisti kitą dieną, perrašant šešis tūkstančius kodų eilutės. Mokymosi kreivė su „javascript“ apskritai nėra kieta, tačiau tai labai gera.

94
30 сент. nustatė Chris Tolworthy rugsėjo 30 d 2011-09-30 13:45 '11, 13:45, 2011-09-30 13:45
@ 4 atsakymai

tl; dr Jei nieko nekalbate, kol viskas įkeliama, turėtumėte būti gerai.


Keisti: peržiūrą, kuri taip pat apima kai kurias ES6 ( let , const ) deklaracijas: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet

Šis keistas elgesys priklauso nuo

  1. Kaip apibrėžti funkcijas ir
  2. Kai juos skambinate.

Štai keletas pavyzdžių.

 bar(); //This won't throw an error function bar() {} foo(); //This will throw an error var foo = function() {} 
 bar(); function bar() { foo(); //This will throw an error } var foo = function() {} 
 bar(); function bar() { foo(); //This _won't_ throw an error } function foo() {} 
 function bar() { foo(); //no error } var foo = function() {} bar(); 

Taip yra dėl to, kas vadinama kėlimu !

Funkcijas galima apibrėžti dviem būdais: funkcijos deklaracija ir funkcijos išraiška. Skirtumas yra erzina ir minutė, taigi tiesiog pasakykime tai šiek tiek neteisingą dalyką: jei jį parašysite kaip function name() {} , tai yra pranešimas , ir kai jį rašote kaip var name = function() {} (arba anoniminę funkciją, priskirtą grįžti , tokie dalykai), tai yra funkcijos išraiška .

Pirma, pažiūrėkime, kaip tvarkomi kintamieji:

 var foo = 42; //the interpreter turns it into this: var foo; foo = 42; 

Dabar, kaip apdorojamos funkcijos deklaracijos:

 var foo = 42; function bar() {} //turns into var foo; //Insanity! It now at the top function bar() {} foo = 42; 

var operatoriai „mesti“ „ foo “ kūrimą į pačią viršūnę, bet vis dar nesuteikia jam vertės. Funkcija deklaruojama taip, ir galiausiai reikšmė priskiriama foo .

Ką apie tai?

 bar(); var foo = 42; function bar() {} //=> var foo; function bar() {} bar(); foo = 42; 

Į viršų pereina tik skelbimas. Priskyrimas įvyksta tik po to, kai skambinama į bar , kurioje jis buvo prieš visus liftus.

Galiausiai, trumpai:

 bar(); function bar() {} //turns to function bar() {} bar(); 

Dabar, kaip apie funkcines išraiškas?

 var foo = function() {} foo(); //=> var foo; foo = function() {} foo(); 

Kaip ir įprastiniai kintamieji, pirmasis foo deklaruojamas aukščiausiame regiono taške, tada jam priskiriama reikšmė.

Pažiūrėkime, kodėl antrasis pavyzdys sukelia klaidą.

 bar(); function bar() { foo(); } var foo = function() {} //=> var foo; function bar() { foo(); } bar(); foo = function() {} 

Kaip matėme anksčiau, iškeltas tik „ foo “ kūrimas, priskyrimas vyksta tada, kai jis atsirado „originaliame“ kode. Kai vadinama bar , foo priskiriama reikšmė, todėl foo === undefined . Dabar funkciniame kūno bar , kaip darant undefined() , kuris sukelia klaidą.

262
30 сент. Atsakymas pateikiamas Zirak 30 sep . 2011-09-30 16:13 '11, 16:13, 2011-09-30 16:13

Pagrindinė priežastis tikriausiai yra ta, kad JSLint failą sudaro tik vienas leidimas, taigi jis nežino, kad apibrėžiate tokią funkciją.

Jei naudojote sintaksės instrukcijų funkcijas

 function foo(){ ... } 

Tiesą sakant, nėra jokio skirtumo, kai skelbiate funkciją (ji visada elgiasi taip, tarsi deklaracija būtų pradžioje).

Kita vertus, jei jūsų funkcija buvo nustatyta kaip reguliarus kintamasis

 var foo = function() { ... }; 
border=0

Turite įsitikinti, kad prieš jį inicijuodami neprisijungiate (tai gali būti klaidų šaltinis).


Kadangi kodo tonų pertvarkymas yra sudėtingas ir gali būti klaidų šaltinis, siūlau ieškoti sprendimo. Aš tikiu, kad galite įvesti JSLint pasaulinių kintamųjų pavadinimą, kad jis nepraneštų apie nedeklaruotus dalykus.

Paskelbkite komentarą apie failo pradžią.

  

Arba galite naudoti teksto laukelį. (Aš taip pat manau, kad galite perduoti jį vidinės jslint funkcijos argumentams, jei galite jį kištis.)

6
30 сент. atsakymas duotas hugomg 30 sep . 2011-09-30 16:14 '11, 16:14, 2011-09-30 16:14

Yra per daug žmonių, kurie paspaudžia savavališkas taisykles, kaip rašyti „JavaScript“. Dauguma taisyklių yra šiukšlės.

Kėlimo funkcija yra „JavaScript“ funkcija, nes ji yra gera idėja.

Kai turite vidinę funkciją, kuri dažnai yra vidinių funkcijų naudingumas, pridėjimas prie išorinės funkcijos pradžios yra priimtinas rašymo kodo stilius, tačiau jis turi trūkumų, kuriuos turite išsamiai perskaityti, kad gautumėte tai, ką veikia išorinė funkcija.

Turite laikytis vieno principo visoje savo kodo bazėje arba pirmiausia arba paskutiniu metu į savo modulį ar funkciją įdėti privačias funkcijas. „JSHint“ yra tinkamas nuoseklumui, bet jūs turite ABSOLUTELY reguliuoti .jshintrc, kad atitiktų jūsų poreikius, NEGALITE ištaisyti kitų žmonių kodavimo sąvokų kodo.

Vienas kodavimo stilius, kurį galite matyti lauke, turėtų būti vengiamas, nes jis nesuteikia jums jokių privalumų ir tik refactoring:

 function bigProcess() { var step1,step2; step1(); step2(); step1 = function() {...}; step2 = function() {...}; } 

Būtent tai reikia vengti. Tiesiog mokykitės kalbos ir naudokite jos stipriąsias puses.

3
18 апр. Henrik Vendelbo atsakymas balandžio 18 d 2015-04-18 17:10 '15, 17:10 pm 2015-04-18 17:10

Tik funkcijos deklaravimas nėra deklaruojamas kaip išraiškos (priskyrimo) funkcija.

1
13 дек. atsakymą pateikė Abhay Srivastav 13 d. 2017-12-13 08:46 '17, 08:46 2017-12-13 08:46

Kiti klausimai apie „ žymų arba „ Užduoti klausimą“