var functionName = function() {} vs function functionName() {}
Olen hiljattain alkanut ylläpitää jonkun toisen JavaScript-koodia. Korjaan virheitä, lisään ominaisuuksia ja yritän myös siistiä koodia ja tehdä siitä johdonmukaisempaa.
Edellinen kehittäjä käyttää kahta tapaa ilmoittaa funktioita, enkä voi selvittää, onko siihen jokin syy vai ei.
Nämä kaksi tapaa ovat:
var functionOne = function() {
// Some code
};
function functionTwo() {
// Some code
}
Mitkä ovat syyt näiden kahden eri menetelmän käyttöön ja mitkä ovat kummankin hyvät ja huonot puolet? Voidaanko toisella menetelmällä tehdä jotakin sellaista, mitä ei voida tehdä toisella?
6622
3
Ero on siinä, että
functionOne
on funktion lauseke ja siten määritelty vasta, kun kyseinen rivi saavutetaan, kun taasfunctionTwo
on funktion julistus ja määritellään heti, kun sitä ympäröivä funktio tai skripti suoritetaan (hoisting vuoksi).Esimerkiksi funktion lauseke:
Ja funktion julistus:
Tämä tarkoittaa myös sitä, ettet voi'ehtoisesti määritellä funktioita funktiodeklaraatioiden avulla:
Ylläoleva määrittelee
functionThree
riippumattatest
'n arvosta — elleiuse strict
ole voimassa, jolloin se vain aiheuttaa virheen.Ensin haluan korjata Gregin:
function abc(){}
on scoped too — nimiabc
on määritelty scope, jossa tämä määritelmä esiintyy. Esimerkki:Toiseksi on mahdollista yhdistää molemmat tyylit:
xyz
määritellään tavalliseen tapaan,abc
on määrittelemätön kaikissa selaimissa paitsi Internet Explorer — älä luota sen määrittelyyn. Mutta se määritellään sen rungon sisällä:Jos haluat alias-funktioita kaikissa selaimissa, käytä tällaista ilmoitusta:
Tässä tapauksessa sekä
xyz
ettäabc
ovat saman objektin aliaksia:Yksi pakottava syy käyttää yhdistettyä tyyliä on funktio-objektien "name" -attribuutti (ei tuettu Internet Explorerissa). Periaatteessa kun määrittelet funktion kuten
sen nimi annetaan automaattisesti. Mutta kun määrittelet sen kuten
sen nimi on tyhjä — loimme anonyymin funktion ja osoitimme sen jollekin muuttujalle.
Toinen hyvä syy käyttää yhdistettyä tyyliä on käyttää lyhyttä sisäistä nimeä viittaamaan itseensä ja antaa samalla pitkä, ristiriidaton nimi ulkoisille käyttäjille:
Yllä olevassa esimerkissä voimme tehdä saman ulkoisella nimellä, mutta siitä tulee liian hankalaa (ja hitaampaa).
(Toinen tapa viitata itseensä on käyttää
arguments.callee
, joka on kuitenkin suhteellisen pitkä, eikä sitä tueta strict-tilassa.))Syvällä sisimmässään JavaScript käsittelee molempia lausekkeita eri tavalla. Tämä on funktioilmoitus:
abc
tässä määritellään kaikkialla nykyisessä laajuudessa:Lisäksi se nostetaan
return
-lauseen kautta:Tämä on funktion lauseke:
xyz
tässä määritellään osoittamispisteestä käsin:Funktioilmoitus vs. funktioilmaus on todellinen syy siihen, miksi Gregin osoittama ero on olemassa.
Hauska fakta:
Henkilökohtaisesti pidän enemmän "function expression" -ilmoituksesta, koska näin voin hallita näkyvyyttä. Kun määrittelen funktion kuten
tiedän, että olen määritellyt funktion paikallisesti. Kun määrittelen funktion kuten
Tiedän, että määrittelin sen globaalisti edellyttäen, etten määrittänyt
abc
:tä missään kohdassa soveltamisalojen ketjussa. Tämä määrittelytyyli on kestävä myös silloin, kun sitä käytetääneval()
:n sisällä. Vaikka määritelmäriippuu asiayhteydestä ja saattaa jättää arvailun varaan, missä se oikeastaan määritellään, erityisesti
eval()
— tapauksessa, vastaus on: Se riippuu selaimesta.Tietojenkäsittelytieteen termeissä puhutaan nimettömistä funktioista ja nimetyistä funktioista. Tärkein ero on mielestäni se, että nimetön funktio ei ole sidottu nimeen, mistä nimi anonyymi funktio johtuu. JavaScriptissä se on ensimmäisen luokan objekti, joka ilmoitetaan dynaamisesti ajon aikana.
Lisätietoja anonyymeistä funktioista ja lambdalaskennasta saa Wikipediasta (http://en.wikipedia.org/wiki/Anonymous_function).