Funktion lausekkeet

joulu 7, 2021

Javaskriptissä funktio ei ole ”maaginen kielirakenne”, vaan erityyppinen arvo.

Aiemmin käyttämäämme syntaksia kutsutaan funktion julistukseksi:

function sayHi() { alert( "Hello" );}

Funktioiden luomiseksi voidaan käyttää myös toista syntaksia, jonka nimi on funktioilmaisu.

Se näyttää tältä:

let sayHi = function() { alert( "Hello" );};

Tässä funktio luodaan ja osoitetaan muuttujaan eksplisiittisesti, kuten mikä tahansa muu arvo. Riippumatta siitä, miten funktio määritellään, se on vain arvo, joka tallennetaan muuttujaan sayHi.

Näiden koodinäytteiden merkitys on sama: ”luo funktio ja laita se muuttujaan sayHi”.

Voidaan jopa tulostaa tuo arvo käyttämällä alert:

function sayHi() { alert( "Hello" );}alert( sayHi ); // shows the function code

Huomaa, että viimeisellä rivillä funktiota ei ajeta, koska sayHi:n perässä ei ole sulkuja. On ohjelmointikieliä, joissa funktion nimen mainitseminen aiheuttaa sen suorittamisen, mutta JavaScript ei ole sellainen.

Javaskriptissä funktio on arvo, joten voimme käsitellä sitä arvona. Yllä oleva koodi näyttää sen merkkijonoesityksen, joka on lähdekoodi.

Totta kai funktio on erityinen arvo siinä mielessä, että voimme kutsua sitä kuten sayHi().

Mutta se on silti arvo. Voimme siis työskennellä sen kanssa kuten muunkinlaisten arvojen kanssa.

Voidaan kopioida funktio toiseen muuttujaan:

function sayHi() { // (1) create alert( "Hello" );}let func = sayHi; // (2) copyfunc(); // Hello // (3) run the copy (it works)!sayHi(); // Hello // this still works too (why wouldn't it)

Katsotaan, mitä edellä tapahtuu yksityiskohtaisesti:

  1. Funktiojulistus (1)muodostaa funktiota ja sijoittaa sen muuttujaan, jonka nimenä on sayHi.
  2. Rivi (2) kopioi sen muuttujaan func. Huomaa jälleen: sayHi jälkeen ei ole sulkuja. Jos olisi, niin func = sayHi() kirjoittaisi kutsun sayHi() tuloksen func:een, ei itse funktiota sayHi.
  3. Nyt funktiota voidaan kutsua sekä sayHi() että func().

Huomaa, että olisimme voineet myös käyttää funktiolauseketta sayHi:n julistamiseen ensimmäisellä rivillä:

let sayHi = function() { alert( "Hello" );};let func = sayHi;// ...

Kaikki toimisi samalla tavalla.

Miksi lopussa on puolipiste?

Voi ihmetellä, miksi funktion lausekkeen lopussa on puolipiste ;, mutta funktion julistuksessa ei:

function sayHi() { // ...}let sayHi = function() { // ...};

Vastaus on yksinkertainen:

  • Koodilohkojen ja niitä käyttävien syntaksirakenteiden, kuten if { ... }, for { }, function f { } jne. lopussa ei tarvita ;.
  • Funktiolauseketta käytetään lausekkeen sisällä: let sayHi = ...;, arvona. Se ei ole koodilohko, vaan pikemminkin osoitus. Puolipiste ; suositellaan lausekkeiden loppuun riippumatta siitä, mikä arvo on. Tässä oleva puolipiste ei siis liity itse funktiolausekkeeseen, se vain päättää lausekkeen.

Palautusfunktiot

Katsotaan lisää esimerkkejä funktioiden välittämisestä arvona ja funktiolausekkeiden käytöstä.

Kirjoitetaan funktio ask(question, yes, no), jolla on kolme parametria:

question Kysymyksen teksti yes Funktio, joka ajetaan, jos vastaus on ”Kyllä” no Funktio, joka ajetaan, jos vastaus on ”Ei”

Funktion pitäisi kysyä question ja kutsua käyttäjän vastauksesta riippuen yes() tai no():

function ask(question, yes, no) { if (confirm(question)) yes() else no();}function showOk() { alert( "You agreed." );}function showCancel() { alert( "You canceled the execution." );}// usage: functions showOk, showCancel are passed as arguments to askask("Do you agree?", showOk, showCancel);

Käytännössä tällaiset funktiot ovat varsin hyödyllisiä. Suurin ero tosielämän ask:n ja yllä olevan esimerkin välillä on se, että tosielämän funktiot käyttävät monimutkaisempia tapoja olla vuorovaikutuksessa käyttäjän kanssa kuin yksinkertainen confirm. Selaimessa tällainen funktio piirtää yleensä mukavan näköisen kysymysikkunan. Mutta se on toinen tarina.

ask:n argumentteja showOk ja showCancel kutsutaan takaisinkutsufunktioiksi tai vain takaisinkutsuiksi.

Ajatuksena on, että välitämme funktiota ja odotamme, että sitä ”kutsutaan takaisin” myöhemmin tarvittaessa. Meidän tapauksessamme showOk tulee callback ”kyllä”-vastaukselle ja showCancel ”ei”-vastaukselle.

Voidaan käyttää funktiolausekkeita saman funktion kirjoittamiseen paljon lyhyemmin:

function ask(question, yes, no) { if (confirm(question)) yes() else no();}ask( "Do you agree?", function() { alert("You agreed."); }, function() { alert("You canceled the execution."); });

Tässä funktiot julistetaan suoraan ask(...)-kutsun sisällä. Niillä ei ole nimeä, joten niitä kutsutaan anonyymeiksi. Tällaisiin funktioihin ei pääse käsiksi ask:n ulkopuolelta (koska niitä ei osoiteta muuttujille), mutta juuri sitä me tässä haluamme.

Tällaista koodia esiintyy skripteissämme hyvin luontevasti, se on JavaScriptin hengen mukaista.

Funktio on arvo, joka edustaa ”toimintaa”

Säännölliset arvot, kuten merkkijonot tai numerot, edustavat dataa.

Funktio voidaan mieltää toiminnaksi.

Voitamme välittää sen muuttujien välissä ja suorittaa sen silloin kun haluamme.

Funktion lauseke vs. funktiodeklaraatio

Muodostetaan keskeiset erot funktiodeklaraatioiden ja lausekkeiden välillä.

Ensiksi syntaksi: miten ne erotetaan toisistaan koodissa.

  • Funktion julistus: funktio, joka julistetaan erillisenä lausekkeena koodin päävirrassa.

    // Function Declarationfunction sum(a, b) { return a + b;}

  • Funktion lauseke: funktio, joka on luotu lausekkeen tai jonkin muun syntaksikonstruktion sisälle. Tässä funktio luodaan ”osoituslausekkeen” oikealle puolelle =:

    // Function Expressionlet sum = function(a, b) { return a + b;};

Hienovaraisempi ero on siinä, milloin funktio luodaan JavaScript-moottorin toimesta.

Funktioilauseke luodaan, kun suoritus saapuu sinne, ja se on käyttökelpoinen vasta siitä lähtien.

Kun suoritusvirta siirtyy osoituksen oikealle puolelle let sum = function… – tässä mennään, funktio on luotu ja sitä voidaan käyttää (osoittaa, kutsua jne. ) tästä lähtien.

Funktion julistukset ovat erilaisia.

Funktiojulistusta voidaan kutsua aikaisemmin kuin se on määritelty.

Esimerkiksi globaali funktiojulistus näkyy koko skriptissä riippumatta siitä, missä se on.

Se johtuu sisäisistä algoritmeista. Kun JavaScript valmistelee skriptin suorittamista, se etsii ensin skriptistä globaalit funktio-ilmoitukset ja luo funktiot. Voimme ajatella sitä ”alustusvaiheena”.

Ja kun kaikki Function Declarations on käsitelty, koodi suoritetaan. Näin tapahtuisi vain rivillä (*). Liian myöhäistä.

Funktioilmoitusten toinen erityispiirre on niiden lohkon laajuus.

Tarkassa tilassa, kun funktioilmoitus on koodilohkon sisällä, se näkyy kaikkialla lohkon sisällä. Mutta ei sen ulkopuolella.

Kuvitellaan esimerkiksi, että meidän täytyy julistaa funktio welcome() riippuen muuttujasta age, jonka saamme ajon aikana.

Tässä on toinen esimerkki:

let age = 16; // take 16 as an exampleif (age < 18) { welcome(); // \ (runs) // | function welcome() { // | alert("Hello!"); // | Function Declaration is available } // | everywhere in the block where it's declared // | welcome(); // / (runs)} else { function welcome() { alert("Greetings!"); }}// Here we're out of curly braces,// so we can not see Function Declarations made inside of them.welcome(); // Error: welcome is not defined

Mitä voimme tehdä saadaksemme muuttujan welcome näkyviin lohkon if ulkopuolelle?

Oikea lähestymistapa olisi käyttää funktio-lauseketta (Function Expression) ja määrätä muuttuja welcome muuttujalle, joka on julistettu lohkossa if ja jolla on asianmukainen näkyminen.

Tämä koodi toimii tarkoitetulla tavalla:

let age = prompt("What is your age?", 18);let welcome;if (age < 18) { welcome = function() { alert("Hello!"); };} else { welcome = function() { alert("Greetings!"); };}welcome(); // ok now

Tai voisimme yksinkertaistaa sitä vielä enemmän käyttämällä kysymysmerkkioperaattoria ?:

let age = prompt("What is your age?", 18);let welcome = (age < 18) ? function() { alert("Hello!"); } : function() { alert("Greetings!"); };welcome(); // ok now

Milloin kannattaa valita funktion julistus vs. funktion lauseke?

Nyrkkisääntönä voidaan sanoa, että kun joudumme julistamaan funktion, harkitsemme ensin Function Declaration -syntaksia. Se antaa enemmän vapautta koodimme järjestämisessä, koska voimme kutsua tällaisia funktioita ennen kuin ne on julistettu.

Se on myös parempi luettavuuden kannalta, koska function f(…) {…} on helpompi etsiä koodista kuin let f = function(…) {…};. Funktioilmoitukset ovat ”silmiinpistävämpiä”.

…Mutta jos Funktioilmoitus ei jostain syystä sovi meille, tai tarvitsemme ehdollisen ilmoituksen (näimme äsken esimerkin), on käytettävä Funktioilmaisua.

Yhteenveto

  • Funktiot ovat arvoja. Niitä voidaan osoittaa, kopioida tai julistaa missä tahansa koodin kohdassa.
  • Jos funktio julistetaan erillisenä lausekkeena pääkoodivirrassa, sitä kutsutaan ”Funktion julistukseksi”.
  • Jos funktio luodaan osana lauseketta, sitä kutsutaan ”Funktion lausekkeeksi”.
  • Funktion julistukset käsitellään ennen koodilohkon suorittamista. Ne ovat näkyvissä kaikkialla lohkossa.
  • Funktion lausekkeet luodaan, kun suoritusvirta saavuttaa ne.

Useimmissa tapauksissa, kun joudumme julistamaan funktiota, Funktion julistus on suositeltavampi, koska se on näkyvissä ennen itse julistusta. Se antaa meille enemmän joustavuutta koodin organisoinnissa, ja se on yleensä luettavampi.

Meidän tulisi siis käyttää funktion lauseketta vain silloin, kun funktion julistus ei sovellu tehtävään. Olemme nähneet pari esimerkkiä tästä tässä luvussa, ja tulemme näkemään lisää tulevaisuudessa.

Vastaa

Sähköpostiosoitettasi ei julkaista.