Funkcionális JavaScript és a modul minta
Az alábbiakban egy kis kitérőre invitálom az olvasót. A közeljövőben a JavaScript olyan – elsősorban a funkcionális programozásból ismert – vetületeit kívánom érinteni, amelyek talán kevesebbek számára ismertek, noha akár mindennapi eszközeink közé tartozhatnának. Ez egy bejegyzés, de talán több is lesz majd belőle.
Vegyük egy függvény deklaráció vázát procedurális programozásból:Illetve vegyük ugyanezt más szintaktikával:Működésüket tekintve megegyeznek, két egymással ekvivalens felírást láttunk, hordozott jelentésükben azonban eltérnek. Utóbbi szintaktika sugallja, hogy a bevezetett függvényre ugyanazok a szabályok fognak vonatkozni, amelyet a változóknál megszoktunk; ugyanúgy hivatkozhatunk rá, ugyanúgy paraméterül adható egy másik függvénynek, ugyanaz lesz a láthatósága stb.
Igazság szerint a második nyelvtan egy névtelen függvényt hoz létre, és egyúttal egy változóhoz köti, hogy később hivatkozni lehessen rá. Bizonyára mindenki által ismert példa aMásik kényelmes használata a névtelen függvényeknek a lambda kalkulus. Vegyük példának okáért a Módosítsuk úgy, hogy a referencia átadása helyett magát a (névtelen) függvény deklarációt írjuk paraméterként.Egyik esetben sem hívjuk meg a függvényt, tehát nem a visszatérési értékét adjuk argumentumként. Megtehetnénk persze azt is.Helyettesítsük be a hívásba az Érdekességképpen ugyanez Lispben.Ha a fenti sémát kiterjesztjük, és a függvény primitív típus helyett objektum literállal tér vissza, akkor meg is érkeztünk Douglas Crockford nyomán a JavaScript alapú fejlesztés egyik népszerű mintájához, a module patternhez.A minta arra apellál, hogy egy névtelen függvényen belül létrehozott további objektumok (akár függvények) a JavaScript láthatósági szabályai értelmében csak akkor látszanak a külvilág felé, ha azokat explicit „kivisszük”. A korábbi példában bemutatott módszert alkalmazva a
■ Vegyük egy függvény deklaráció vázát procedurális programozásból:
function megcsinalom(ezt)
{
//keményen dolgozom
}
var megcsinalom = function(ezt)
{
//keményen dolgozom
}
Igazság szerint a második nyelvtan egy névtelen függvényt hoz létre, és egyúttal egy változóhoz köti, hogy később hivatkozni lehessen rá. Bizonyára mindenki által ismert példa a
req.onreadystatechange = megcsinalom;
séma, amely a req
[a példa kedvéért feltételezett XMLHttpRequest
objektum] onreadystatchange
tulajdonságának értékül adja a megcsinalom
által mutatott – az esetek többségében egy függvény – objektumot. Ilyettébb módon akár azt is írhattuk volna, hogyxmlHttp.onreadystatechange = function(allapot)
{
//keményen dolgozom állapot valtozás esetén
}
storage
objektum putString
metódusát, amely harmadik argumentumként egy állapotkezelő callback függvényt vár. Az alábbit írhatnók fel:storage.putString("kulcs", JSON.stringify(adatok), figyelem);
storage.putString("adatok", JSON.stringify(adatok), function(allapot)
{
//keményen dolgozom állapot változás esetén
});
var osszead = function(a, b) {return a + b;}
var osszeg = osszead(3, 5); //8
osszead
referenciája helyett magát a névtelen függvényt.var osszeg = function(a, b) {return a + b;}(3, 5);
(setf osszeg ((lambda (a b) (+ a b)) 3 5))
var modul = function()
{
//privát
function _metodus() {}
//publikus
function metodus() {}
return {metodus: metodus}
}();
modul
értékül fogja kapni a névtelen függvénytől visszakapott, a nyílvános tagfüggvényeket és változókat tartalmazó objektumot. A modul minta rendkívül jól alkalmazható névtér ütközések és az érzékeny adatok illetéktelen, kontrollálatlan módosításának elkerülésére.
függvény literál szintaxisa
(function() { // This function has no name.
// Code goes here.
// Any variables declared become properties of the call
// object instead of cluttering up the global namespace.
})(); // end the function literal and invoke it now.
Note that the parentheses around the function literal are required by JavaScript syntax
JavaScript: The Definitive Guide, 5th Edition, 8.8.3. The Call Object as a Namespace
:S
üdv Csaba
Single expression
Tehát míg a
safari2
Cs.
lambdázás
sikerült is betömnie nálam egy fehér lyukat a js megértésében, mégpedig a lambdvábal kapcsolatban
thx!
debuggolásnál jól jön a név
function foo()
alakú deklarációt a debugger/profiler foo() néven fogja jelezni, avar foo = function()
alakút meg function() néven, ami elég zavaró tud lenni, ha sok van belőle.Hát igen
a rekurzív hívású
arguments.callee
arguments.callee
személyében.csak tiszta forrásból :))
var f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); };
This line of code defines an unnamed function and stores a reference to it in the variable f. It does not store a reference to the function into a variable named fact, but it does allow the body of the function to refer to itself using that name. Note, however, that this type of named function literal was not properly implemented before JavaScript 1.5.
from Javascript Definitive Guide 8.1.2. Function Literals , jó a callee-ra tényleg azt írják hogy
In addition to its array elements, the Arguments object defines a callee property that refers to the function that is currently being executed. This property is rarely useful, but it can be used to allow unnamed functions to invoke themselves recursively. For instance, here is an unnamed function literal that computes factorials:
function(x) {
if (x <= 1) return 1;
return x * arguments.callee(x-1);
}
Cs.
hozzászólás
Én nem vágom mire jó ezzel trükközni :-) ismerem ezt a mintát, de sosem tartottam a gyakorlatban használhatónak. Mmint a modul mintát tutira nem használnám sehol a többit, amit írtál viszont nagyon gyakran.
Én úgy vagyok vele, hogy elfogadtam, hogy jsben nincs olyan szinten private változó, mint a legtöbb nyelvben, szóval nem szenvedtem vele sokat.. max extrém esetekben jó a dolog, de ahol már öröklés meg komolyabb dolgok vannak, ott nem ér semmit. (nekem legalábbis ebbe tört bele a bicskám, amikor private változós classeket akartam még jó régen csinálni jsben)
Persze ettől függetlenül, ha tudsz komoly példát mutatni, ahol tényleg nagyon hasznos a dolog, akkor azt mondom oks :) tévedtem
szerk:
közben leesett, hogy használok elég sok helyen hasonló dolgokat, csak hát így jár, aki nem ismeri a minták elnevezéseit :P
pl:
(aki nem értené a példában a tömb push metódusát írtam felül úgy, hogy az eredeti pusht hívja meg, de szigorúan csak egy hozzáfűzendő elemmel, a visszatérő érték pedig maga a tömb lesz, és nem a tömb hossza)