Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: JavaScript: Kaksi tapaa funktion määritykseen

Sivun loppuun

HTML5 [08.02.2014 18:00:41]

#

JavaSciptissähän funktio määritellään seuraavasti:

function teeJotakin() {
    // koodia…
}

Opin tänään toisen tavan luoda funktio:

var teeJotakin = function() {
    // koodia…
};

Onko näillä kahdella tavalla jotakin muuta eroa kuin koodin muoto ja se, että ensimmäinen määritetään jäsennys- ja toinen suoritusvaiheessa?

Triton [08.02.2014 23:40:03]

#

Mitä nyt itse olen JS:ssää duunissa koodaillut, niin en vielä tähän päivään mennessä ole ainakaan huomannut, että toinen notaatio toimisi jotenkin erilailla kuin toinen. Jälkimmäisessä tapauksessa luot nk. anonyymin funktion jonka sijoitat muuttujan arvoksi. Ensimmäisessä taas luot nimetyn funktion.

Edit.

Itse asiassa javascriptissä on vielä kolmaskin tapa luoda funktioita:

var sum = new Function( 'a', 'b', 'return a + b' );
sum( 1, 2 ) //= 3

Lebe80 [08.02.2014 23:40:48]

#

Toista pystyy helposti käyttämään vaikka useassa paikassa, kun se on muuttujassa.

The Alchemist [09.02.2014 00:06:55]

#

Useassa paikassa? Samalla tavallahan nuo ovat kutsuttavissa.

Jaska [09.02.2014 00:21:05]

#

SO:ssa on juttua asiasta.

groovyb [09.02.2014 20:41:32]

#

kai tuo on enemmänkin käyttötarkoitus -juttu.

Oletetaan vaikka, että haluat tehdä oman ajax -wrapperin, keskitetyllä virheenhallinnalla, ja antaa success function parametrin sisällä:

$("#AnotherButton").click(function() {

   var options = {
     url: 'Another.php',
     data: { anotherParam: $("#anotherField").val() },
     success: function() {
        alert('You clicked the second button!');
     }

   };

   ajaxCall(options);

});

$("#SomeButton").click(function() {

   var options = {
     url: 'Something.php',
     data: { someParam: $("#someField").val() },
     success: function() {
        alert('You clicked the first button!');
     }

   };

   ajaxCall(options);

});


function ajaxCall(options) {
$("#errorContainer").empty();
$.ajax({
  type: "POST",
  url: options.url,
  data: options.data,
  success: options.success,
  error: function(jqXHR,textStatus,errorThrown) {
     var errorMessage = errorThrown || jqXHR.statusText;
      $("#errorContainer").append(errorMessage);
  }
});

}

The Alchemist [09.02.2014 21:35:01]

#

En kyllä tajua, mitä tuo groovyb:n esimerkki yrittää havainnollistaa. Se taitaa olla liian pitkä ja pointti häviää jonnekin.

jlaire [09.02.2014 22:14:00]

#

Jälkimmäisessä muuttujan arvoksi voi myöhemmin asettaa jonkin toisen arvon. Tämä ei kuitenkaan yleensä ole hyödyllistä.

Käytännöllinen ongelma on, että jälkimmäisen tavan voi helposti sekoittaa tähän idiomaan:

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

// Tai jopa näin.
var foo = function() {
    ...
}();

groovyb [09.02.2014 22:16:19]

#

ideana oli se, että riippuen käyttötarkoituksesta, valitaan tapa esitellä funktio.
esimerkissä havainnollisestettiin sitä, miten funktio siirretään parametrina toiseen funktioon.

function Something() {
  var nn = {
     someFunc : function() { alert('test'); }
  };
  AnotherFunc(nn);
}

function AnotherFunc(options)
{
   //Use the options.someFunc
}

jlaire [09.02.2014 22:19:20]

#

groovyb: luepa nyt alkuperäinen kysymys uudestaan. Kyllä me tiedetään mitä nimettömät funktiot ovat.

groovyb [09.02.2014 22:22:42]

#

jlaire, ekassa viestissänihän vastasin että käyttötarkoituksen mukaan valitaan tapa. Ei niissä käytännössä ole eroa funktion kutsumisen osalta. Toisessa viestissä avasin esimerkkiäni, jos sen sisällön tarkoitus ei auennut. ja en tiedä nyt puhutko myös OP:n puolesta viestilläsi "kyllä me tiedetään mitä nimettömät funktiot ovat", koska en tarkoituksella osoittanut viestiäni juuri sinulle.

jlaire [09.02.2014 22:25:19]

#

SomeFunc ei ole kummankaan tavan mukainen. En ymmärrä miten esimerkkisi liittyy aiheeseen.

Kysymys on miten valita nimetyn funktion ja muuttujan välillä, jonka arvoksi asetetaan nimetön funktio.

"Meillä" viittasin kaikkiin keskusteluun osallistuneisiin.

groovyb [09.02.2014 22:34:49]

#

itseasiassa, kyllä se periaatteessa on aiheen mukainen (se että en kierrättänyt funktiota esimerkissä erillisen muuttujan kautta ei muuta itse asiaa, miksi funktiota luodaan tarvittaessa muuttujaan, perinteisen tavan sijaan). Vai näetko suurta eroa tässä:

var something = {
    nn : function() {}
}

//vs

var somefunc = function() {};
var somethingElse = {
    xx: somefunc
}

jlaire [09.02.2014 22:36:01]

#

groovyb kirjoitti:

var something = {
    nn : function() {};
}

Nään syntaksivirheen. :---D

Meen nukkuu.

The Alchemist [09.02.2014 22:48:12]

#

Funktion voi kyllä antaa parametrina vaikkei se olisikaan "muuttujaan esitelty funktio". Esimerkki ei siis ole lainkaan havainnollinen, koska ihan minkä tahansa scopessa olevan funktion voi antaa parametrina.

groovyb [09.02.2014 22:48:53]

#

Idea kuitenkin varmasti sinulle aukesi. ja vastauksen sidos alkuperäiseen kysymykseen. Kauniita unia.

The Alchemist [09.02.2014 22:49:40]

#

Esimerkkisi idea aukesi joo, mutta samalla aukesi sekin, ettei esimerkki tosiaan vastaa ap:n kysymykseen, mikä oli myös minulle se ongelmani.

Metabolix [09.02.2014 22:51:12]

#

Olen kyllä jlaireen kanssa samaa mieltä, että groovyb selittelee jotain ihan omiaan.

Kuten Stack Overflow'ssa selitetään, merkinnöillä on käytännön eroa vain kahdessa asiassa: Nimetyllä funktiolla on nimi. Lisäksi funktiomäärittely (function declaration) on voimassa koodilohkon alusta saakka, vaikka se olisi fyysisesti vasta myöhemmin, kun taas funktiolauseke (function expression) on voimassa vasta siinä kohti, missä se sijaitsee. Alla on esimerkkejä:

// Toimii:
f();
function f() {}

// Toimii:
var f2 = f;
f2();

// Ei toimi:
g();
var g = function() {}

// Eivät toimi:
h1(); h2();
var h1 = function h2() {}

// Chromiumissa toimii, Firefoxissa ei; pitäisi kai toimia:
if (1) {
	i();
	function i() {}
}

Huomattavaa on, että myös funktiolauseke voi olla nimetty funktio. Yllä h-kohdassa luodaan nimetty funktio h2 ja lisäksi sijoitetaan samainen funktio muuttujaan h1. Tulostamalla nähdään, että h1 sisältää funktion nimeltä h2:

alert(h1); // (function h2() {})

groovyb [09.02.2014 22:52:00]

#

The Alchemist, totta. Mutta siksi tuo onkin kysymys oikeasta käyttötarkoituksesta, eikä validista syntaksista. Tähän oikea kysymys voisi olla: Milloin minun tulisi käyttää funktiota muuttujassa, perinteisen funktioesittelyn sijaan?

*Edit*

Tietenkään ei voi käyttää muuttujan sisältämää funktiota ennen muuttujan julistamista, sen nyt odotin olevan melko itsestäänselvää. Eihän tuo eroa mistään muustakaan muuttujasta, sisälsi se sitten tekstiä tai funktion. Muuttujasta harvemmin saa mitään ulos ennenkuin se on julistettu, ja sisään jotain tungettu.

Osaatko kertoa Metabolix, missä selitin omiani? Annoin OP:lle käyttötarkoitusesimerkin muuttujan sisältämästä funktiosta, ja miksi sellaisia käytetään.

Metabolix [09.02.2014 22:59:22]

#

groovyb kirjoitti:

Osaatko kertoa Metabolix, missä selitin omiani? Annoin OP:lle [sitä sun tätä]

Yritäpä nyt lukea, mitä hän kysyi: ”Onko näillä kahdella tavalla jotakin muuta eroa kuin koodin muoto ja se, että ensimmäinen määritetään jäsennys- ja toinen suoritusvaiheessa?”

Osaatko kertoa groovyb, missä kohti aiemmissa viesteissäsi käsittelet jotain tähän kysymykseen liittyvää? Itse en ainakaan näe kysymyksessä mitään pyyntöä muuttujan sisältämän funktion käyttötarkoitusesimerkistä vaan vain siitä, onko mainituilla kahdella tavalla jotain eroa. Jos vielä katsot tuota viestiäni, huomaat ehkä, että nimetyn funktion voi ihan yhtä hyvin laittaa muuttujaan tai mihin tahansa, eli sikäli esimerkkisi on harhaanjohtava, koska esittelet ”eroja”, joita ei edes ole.

groovyb [09.02.2014 23:08:37]

#

"Onko näillä kahdella jotain muuta eroa.."

Tähän kysymykseen vastasin. Toista tapaa käytetään kun halutaan funktio esim. osaksi parametriä (johon tein esimerkin, taitaa olla yleisin syy miksi function expressionia käytetään), toista tapaa käytetään kun halutaan tehdä yleisesti kutsuttava funktio. Molemmilla tavoilla luotua funktiota voi luonnollisesti kutsua kunhan huolehtii siitä että missä vaiheessa koodia kutsu suoritetaan, mutta kysymys on enemmänkin järkevästä tavasta tehdä asioita, kuten useat best practiset ovat myös osoittaneet. javascript kielenähän mahdollistaa aika paljon perverssejä asioita, kuten kaikki sitä käyttävät varmasti tietävät. Se ei silti tarkoita että kaikki asiat tulisi tehdä miten sattuu, vaikka se olisikin mahdollista.

(tästä lisää asiasta kiinnostuneille vaikka täältä)

The Alchemist [10.02.2014 00:50:02]

#

groovyb kirjoitti:

The Alchemist, totta. Mutta siksi tuo onkin kysymys oikeasta käyttötarkoituksesta, eikä validista syntaksista.

No kun ei tuo esimerkki edes hahmottanut käyttötarkoitusta, koska täsmälleen saman esimerkin olisi voinut toteuttaa molemmilla tavoilla eikä kummallakaan tavalla ole mitään etua toiseen nähden. Ja vaikka yrittäisi ajatella asiaa käytännön tarpeiden kannalta, niin silloinkaan mitään eroa ei löydy.

Metabolix [10.02.2014 16:31:57]

#

groovyb kirjoitti:

Toista tapaa käytetään kun halutaan funktio esim. osaksi parametriä – –, toista tapaa käytetään kun halutaan tehdä yleisesti kutsuttava funktio. – – Mutta siksi tuo onkin kysymys oikeasta käyttötarkoituksesta, eikä validista syntaksista.

Vastauksesi on harhaanjohtava. Eri tavoissa ei ole mitään sellaista eroa, jonka takia niitä pitäisi käyttää noin, vaan kaikissa näyttämissäsi tilanteissa voi käyttää kumpaa tahansa tapaa. Ei ole erityistä syytä, miksi jokin näistä olisi ”oikea käyttötarkoitus” ja toinen taas ”väärä käyttötarkoitus”.

Tietenkään eri tapoja ei silti kannata käyttää holtittomasti sekaisin, vaan koodi on selvempää, jos projektissa on jokin linjaus siitä, miten funktiot kirjoitetaan eri tilanteissa.

Merri [10.02.2014 18:08:01]

#

Debuggaamisen kannalta nimettömät funktiot on vähän ilkeitä, joten nyt mm. suorituskyvyä selvitellessä olen alkanut antaa verrattain pitkiä nimiä aiemmin nimettömille funktioille.

var lyhytNimi = function kirjastoModuuliLyhytNimi() { ... };

// tai

$(function kirjastoModuuliAlustus() { ... });

Näkee nopeasti mistä funktio on lähtöisin ja minifioija taas voi lyhentää muuttujan nimeä vielä entisestään.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta