JavaScript függvények
A függvények a JavaScript nyelv talán legfontosabb elemei. Ugyanakkor a függvények azok, amik a legtöbb félreértés áldozatai. Ennek okán úgy gondolom érdemes tisztázni a függvények működését és használatát. A függvények a JavaScriptben elsődleges (first-class) típusok, azaz hozzárendelhetjük őket változókhoz és objektum tulajdonságokhoz, átadhatjuk őket paraméterként más függvényeknek, valamint egy függvény illetve metódus is térhet vissza függvénnyel (egy függvényt metódusnak nevezünk, ha az egy objektum tulajdonsága). A klasszikus programozási nyelvekhez képest (C/C++, Java, PHP) ez a megközelítés idegen, ez is okozhatja a sok problémát az értelmezéssel kapcsolatban.
Függvények létrehozása
Alapvetően háromféleképpen hozhatunk létre függvényeket:
- függvény deklarációval (function declaration)
- függvénykifejezéssel (function expression)
Function
konstruktor használatával.
Függvény deklaráció
A függvények létrehozásának ez a módja talán a legelterjedtebb.
function peldaFuggveny(parameter) {
// függvény törzs
}
Ez a formája a függvényeknek szinte teljesen megegyezik a klasszikus nyelvekben való felírással, azzal a különbséggel, hogy mivel a JavaScript egy szkript nyelv, ezért nincs megadva a változók típusa, valamint hogy a függvény milyen típusú változót ad vissza, sőt az sem, hogy egyáltalán ad-e vissza valamit.
A függvény deklaráció szabályai a következők:
- A függvény deklarációnak kötelezően van neve,
- vagy Program szinten, vagy egy másik függvény törzsében szerepel,
- akkor jön létre, amikor a program futása abba a környezetbe jut,
- módosítja a környezeti változók listáját (variables object).
Ebből a listából szerintem az első pont nem szorul magyarázatra. A 2. pont azt jelenti, hogy vagy a fő programkódban (böngésző esetén közvetlenül <script>
elemben), illetve egy abban levő függvény törzsében szerepelhet. Például:
<script>
function peldaFuggveny1(parameter) {
// függvény törzs
}
</script>
illetve
function foo() {
function peldaFuggveny2() {
// függvény törzs
}
}
A 3. pont pedig azt jelenti, hogy a peldaFuggveny2()
nevű függvény akkor jön létre, amikor a foo()
függvény futása elkezdődik. Ezt a viselkedést – azaz, hogy a függvény felliftezik a környezet tetejére – nevezzük hoistingnak. Azaz:
function foo() {
var bar = peldaFuggveny2(); // a függvény már létezik
function peldaFuggveny2() {
// függvény törzs
}
}
A 4. pont szerint pedig az elérhető változók listája kibővül a függvény nevével. Azaz egy változóhoz hozzárendelhetjük a függvényt, valamint bármilyen más helyen, ahol kifejezést használhatunk, hivatkozhatunk a függvényre a nevével.
Függvénykifejezés
A függvénykifejezés (function expression) létrehozásának szabályai a következők:
- a kódban ott szerepelhet, ahol kifejezés szerepelhet,
- neve elhagyható,
- nem módosítja a környezeti változók listáját,
- akkor jön létre, amikor a program futása rákerül.
Úgy gondolom, hogy az 1. pont szorul a legnagyobb magyarázatra. Kifejezés szerepelhet függvények, illetve konstruktorok paramétereként, és mindenhol máshol, ahol változó szerepelhet. Mit jelent az, hogy a neve elhagyható? Hogyan hivatkozunk akkor majd a függvényünkre? Hát például úgy, hogy hozzárendeljük egy változóhoz, elvégre a függvények elsődleges típusok.
// Hozzárendelhetjük változókhoz.
var foo = function () {
// függvény törzs
};
// Átadhatjuk paraméterként.
foo(function () {
// függvény törzs
});
Ha a függvénykifejezésnek adhatunk nevet, de nem módosítja a környezeti változókat, akkor mire jó? Arra, hogy hivatkozni tudjunk rá a függvényünkön belül.
var foo = function bar(foobar) {
if (foobar) {
bar(!foobar);
}
};
Azonnal meghívott függvénykifejezés
A függvénykifejezés egyik speciális fajtája az azonnal meghívott függvénykifejezés (Immediately-Invoked Function Expression, IIFE), vagy ahogy tévesen régebben nevezték self-executing anonymous function illetve self-invoked anonymous function. Ennek lényege, hogy a függvénykifejezést azonnal meghívjuk.
(function () {
// függvény törzs
})();
Hogyan is működik ez, és miért? A zárójelek hatására a függvényünk függvénykifejezés lesz, mivel a zárójeleken belül csak kifejezés szerepelhet (amennyiben a függvény már eleve olyan helyen szerepel, ahol csak kifejezés szerepelhet, a zárójelek elhagyhatók). Ezt a létrejött függvénykifejezést pedig azonnal meg is hívjuk.
(function foo(bar) {
if (bar) {
foo(false);
}
})('foobar');
Mint látható az azonnal meghívott függvénykifejezésnek nem kell anonimnak lennie, ha hivatkozni szeretnénk rá belülről, akkor adhatunk neki nevet is. Még egyszer tekintsük át, mi is történik itt valójában:
- Létrehozunk egy függvénykifejezést, aminek
foo
a neve, de kívülről nem elérhető. - A függvénykifejezést meghívjuk
'foobar'
paraméterrel. - A függvénykifejezés meghívja magát még egyszer (most már
false
paraméterrel), mivel tud saját magára hivatkozni a nevével.
Miért hasznosak a függvénykifejezések?
Használatukkal elkerülhetjük a globális névtér változókkal való telepiszkítását. Ugyanis a függvényen belül var
kulcsszóval létrehozott változók a függvényen kívül nem léteznek. Ugyanakkor a függvényünk azonnal lefut, és még a függvény a saját nevével se szennyezi a globális névteret, mivel a függvénykifejezés neve nem kerül a környezeti változók közé.
JScript és a függvénykifejezések
Az Microsoft JavaScript implementációja (JScript) nem specifikáció szerint működik, amikor függvénykifejezések nevéről van szó. Ugyanis ha egy függvénykifejezésnek nevet adunk, akkor azt a JScript függvény deklarációnak gondolja teljesen hibásan, azaz a környezeti változók közé is bekerül a függvény. Ezért amennyiben Internet Explorer, vagy más JScript felhasználás is a megcélzott platformok között van, akkor bánjunk óvatosan a függvénykifejezések elnevezésével (például ne ütközzön változó, vagy függvénynevekkel).
Function
konstruktor
Mivel a Function
konstruktor használata kerülendő, nem is foglalkozunk vele túl sokat, igazából csak az alapokat szeretném bemutatni.
var foo = new Function('bar', 'foobar', 'return bar + foobar;');
A Function
konstruktor meghívásakor az átadott paraméterek közül az utolsó lesz a függvény törzse, az előtt opcionálisan megadott paraméterek pedig a függvény paraméterei. Fontos megjegyezni, hogy a new
kulcsszó megadása nem kötelező, nem befolyásolja a működést.
Miért nem ajánlott használni?
Mert a megadott függvény nem abban a környezetben fut le, ahol futtatjuk, hanem a globális névtérben, ezért hozzáférhet a globális névtérben megadott változókhoz, de azokhoz nem, ahol fut.
var foo = 10;
function bar() {
var foo = 20,
foobar = new Function('alert(foo);');
foobar(); // 10;
}
bar();
return
utasítás
Egy függvény visszatérhet futásának bármelyik pontján a return
utasítás segítségével. Amennyiben nem adtunk meg visszatérési értéket (üres return
utasítás), illetve a függvény legvégén nem adtunk ki return
utasítást, akkor a függvény undefined
értékkel tér vissza. A függvény visszatérhet akármilyen értékkel, legyen az valamilyen primitív típus, objektum, vagy akár egy függvény is.
function foo(bar) {
if (bar === true)
return 10;
else if (bar === false) {
return function () {
return false;
};
}
// implicit return undefined
}
Ha egy függvényt a new
kulcsszóval hívunk meg (azaz konstruktorként), akkor a függvény – amennyiben nem adunk ki return
utasítást –, akkor az aktuális this
értékkel tér vissza; és amennyiben nem adunk át paramétereket, akkor a meghívásnál a zárójelek elhagyhatók.
function Foo() {
// implicit return this
}
new Foo;
Closure (lexikai zárvány)
A függvények lehetővé teszik az úgynevezett lexikai zárvány használatát. A zárvány lényege, hogy hozzáférünk a függvényen kívüli változókhoz azután is, hogy a függvényen kívüli környezet már lefutott. Legegyszerűbben egy példával lehet bemutatni a működést.
function foo() {
var bar = 'foobar';
return function barfoo() {
alert(bar);
}
}
var foobar = foo();
foobar(); // 'foobar'
A fenti példában létrehoztunk egy foo()
nevű függvényt, ami visszaad egy függvényt. A visszaadott barfoo()
függvény – amit a foobar
nevű változóban tároltunk el –, továbbra is hozzáfér a bar
nevű változóhoz, holott a foo()
függvény már régen lefutott. Lássuk a következő, igencsak klasszikus példát:
var foo = [], i, j;
for (i = 0; i < 5; i += 1) {
// Függvényeket pakolunk bele a foo tömbbe.
foo.push(function () { return i; });
}
for (j = foo.length - 1; j >= 0; j -= 1) {
// Kiírjuk a konzolra a függvény futásának eredményét.
console.log(foo[j]());
}
A fenti kis program 5 függvényt pakol bele a foo
nevű tömbbe. A függvény visszaadja az i
értékét. Ezután végigmegyünk fordított sorrendben a tömb elemein, és kiíratjuk a függvény futásának eredményét a konzolra. És egyesek meglepetésére minden esetben a konzolra az 5
íródik ki. Miért? Azért mert a függvényünk a zárványt használva hozzáfér az i
értékéhez, és az első for
ciklus futása után i
értéke 5
. Hogyan „javíthatjuk” meg a működést, azaz a függvényünk azt az értéket adja vissza, mint ami i
volt a létrejöttekor?
var foo = [], i, j;
for (i = 0; i < 5; i += 1) {
// Függvényeket pakolunk bele a foo tömbbe.
foo.push(
// IIFE-et hozunk létre, ami bezárja egy closure-be i értékét
function (bar) {
// Ezt a függvényt fogjuk ténylegesen bepakolni a tömbbe
return function () {
// a függvény a bar változót adja vissza, ami i akkori értéke
return bar;
}
}(i)
);
}
for (j = foo.length - 1; j >= 0; j -= 1) {
// Kiírjuk a konzolra a függvény futásának eredményét.
console.log(foo[j]());
}
Most már a foo
tömbbe pakolt függvények hozzáférnek i
eredeti értékéhez (bar
-hoz), mivel azt egy closure-be zártuk. További információt az MDC Closures, illetve Dmitry A. Soshnikov Closures oldalain találunk.
this
A függvényeken belül a this
értéke más nyelvekhez képest több dolgot jelenthet. Lássunk először is egy példát:
function foo() {
console.log(String(this));
}
foo();
var bar = {
foobar: foo
};
bar.foobar();
A fenti kódot böngészőben futtatva a következő kimenetet kapjuk:
[object Window]
[object Object]
Hogy is van ez? Alapvetően azok a függvények, amik nem egy objektum metódusai a window
, vagy más környezetben, más globális névtér objektumot adnak vissza, this
néven. Ilyen a foo()
függvény is. Ugyanakkor, ha mint a bar
objektum metódusaként hívjuk meg, akkor azt az objektumot veszik this
nek, aminek a metódusaként hívtuk meg (példánkban ez a bar
). Most fordítsuk meg a fenti példát:
var bar = {
foobar: function () {
console.log(String(this));
}
},
foo = bar.foobar;
foo();
bar.foobar();
A fenti leírás után remélhetőleg nem lepődik meg senki, hogy ugyanazt a kimenetet kapjuk, mint először. Az ok igencsak egyszerű. A foo()
függvény ugyan a bar
objektum egy metódusa, de nem, mint a bar
objektum metódusa hívtuk meg, ezért a globális névtér objektum (a böngészőkben ez a window
) lett a this
.
call()
és apply()
Minden függvény a JavaScriptben egyben objektum is, és van pár metódusa is. Ilyen metódus a call()
és az apply()
. Hogy ne legyen egyszerű az élet, a this
értékét módosítani is tudjuk ezen metódusok használatával.
function foo(arg1, arg2) {
console.log(String(this), arg1, arg2);
}
var bar = {};
foo.call(bar, "foobar", "barfoo"); // [object Object] foobar barfoo
foo.apply(bar, ["foobar", "barfoo"]); // [object Object] foobar barfoo
A függvények call()
metódusa első paraméterként a this
t várja, a többi paramétert pedig a függvény hagyományos paraméterként kapja meg. Az apply()
metódus annyiban különbözik, hogy egy tömbszerű objektumot vár, mint második paraméter, és annak elemeit adja át a függvénynek paraméterként.
Amennyiben a call()
, illetve apply()
első paramétere null
vagy undefined
, akkor a this
a globális névtér objektumra fog mutatni. Amennyiben valamilyen primitív érték (String, Number, Boolean), akkor az objektumként adódik át, mint this
, azaz lefut rajta a megfelelő típus konstruktora.
var foo = [null, undefined, NaN, true, 0, 'string', [], {}],
i, l;
function bar(arg) {
console.log('this: ', String(this), typeof this, ' | arg: ', arg, typeof arg);
}
for (i = 0, l = foo.length; i < l; i += 1) {
bar.call(foo[i], foo[i]);
}
Kimenetünk:
this: [object Window] object | arg: null object
this: [object Window] object | arg: undefined undefined
this: NaN object | arg: NaN number
this: true object | arg: true boolean
this: 0 object | arg: 0 number
this: string object | arg: string string
this: object | arg: [] object
this: [object Object] object | arg: Object {} object
strict mode
A strict mode használata jelentősen módosít ezen a működésen. Jelenleg strict mode használatára nem sok lehetőség van, de azért megemlítem, miben változnak a dolgok. A call()
, illetve apply()
nem módosítja az átadott paraméter típusát, azaz a null
vagy undefined
értéket első paraméterként átadva null
, illetve undefined
lesz a this
értéke. Ehhez hasonlóan a primitív típusok se alakulnak át objektummá. Ennek megfelelően, amennyiben nem adtunk meg explicit this
értéket a függvény meghívásakor, illetve nem egy objektum metódusaként hívjuk meg, akkor a this
nem a globális objektum lesz, hanem undefined
. További információt a strict mode működéséről az MDC illetve Dmitry A. Soshnikov oldalain találunk.
arguments
objektum
Egy függvény argumentumaihoz a függvényen belül az arguments
objektumon keresztül is hozzáférhetünk. Ez akkor hasznos, amikor változó számú paramétert vár a függvény, illetve ki akarjuk deríteni, hogy ténylegesen mennyi paramétert is adtak át neki a meghíváskor.
function foo() {
console.log(arguments);
}
foo('bar', 'foobar'); // ["bar", "foobar"]
Ugyan az arguments
objektum hasonlít egy tömbre, de sajnos(?) nem az. Rendelekezik egy length
tulajdonsággal, valamint az egyes argumentumokhoz hozzáférhetünk a megfelelő indexek használatával, például az arguments[0]
visszaadja az első paramétert, példánkban ez a bar
. Ennek megfelelően egyszerűen végigmehetünk az összes argumentumon:
function foo() {
var i, l = arguments.length;
for (i = 0; i < l; i += 1) {
alert(arguments[i]);
}
}
Amennyiben az argumentumokat tömbként szeretnénk kezelni, egyszerűen átalakíthatjuk, így ezek után a tömb függvényeit már tudjuk használni:
function foo() {
var args = Array.prototype.slice.call(arguments); // az args már egy tömb.
}
Ezen kívül az arguments
objektum még rendelkezik két tulajdonsággal. Az arguments.callee
egy hivatkozás az éppen futó függvényre, valamint az arguments.caller
egy hivatkozás a függvényt meghívó függvényre. Ez utóbbi kettő használata kerülendő, ugyanis az arguments.caller
már a JavaScript 1.3 óta elavult, az arguments.callee
pedig nem használható strict mode esetén.
Magasabb rendű függvények
A magasabb rendű függvények (higher order function) olyan függvények, melyek más függvényekkel dolgoznak, azaz vagy paraméterként várják őket, vagy függvényeket adnak vissza.
Függvényt fogadó függvények
A ECMAScript 5 tömb metódusainak egy része egy függvényt vár paraméternek (map()
, filter()
, reduce()
, reduceRight()
, forEach()
, every()
, some()
), de ilyen már régen a nyelv részét képező sort()
is. Ezek jellemzően egy függvényt várnak első paraméternek, és a tömb elemein futtatják le ezt a függvényt. Például a tömb sort()
metódusa egy opcionális függvényt vár paraméternek, ami pozitív, negatív, illetve 0 értékkel tér vissza, attól függően, hogy a két összehasonlított érték közül az elsőt nagyobbnak, kisebbnek illetve egyenlőnek tekintjük a másikkal. Például:
var array = [1, 2, 3];
// Rendezzük fordított sorrendben
array.sort(function (a, b) {
if (a < b) {
return 1;
}
else if (a > b) {
return -1;
}
else {
return 0;
}
});
console.log(array); // [3, 2, 1]
Magunk is létrehozhatunk hasonló függvényeket:
function calculate(func, a, b) {
return func(a, b);
}
function add(a, b) {
returm a + b;
}
function multiply(a, b) {
return a * b;
}
calculate(multiply, 5, 3); // 15
calculate(add, 5, 3); // 8
Amennyiben ECMAScript 5-öt nem ismerő környezetben akarunk végrehajtani a tömb összes elemén egy függvényt, akkor azt megtehetjük például a következőképpen:
function each(array, func) {
var i, l = array.length;
for (i = 0; i < l; i += 1) {
func(array[i]);
}
}
// Írjuk ki a tömb összes elemét, egyesével:
each([1, 2, 3], console.log);
Amennyiben a tömbből egy új tömböt akarunk generálni, használhatjuk például a map()
függvényt:
function map(array, func) {
var i, l = array.length, retArray = [];
for (i = 0; i < l; i += 1) {
// Minden elemre lefut a megkapott függvény,
// aminek eredményével feltöltjük a tömböt.
retArray[i] = func(array[i]);
}
return retArray;
}
map([1, 2, 3], function (a) { return a + 1 }); // [2, 3, 4]
A nyelvben persze más függvények is tekinthetők magasabb rendűnek, ugyanis például a setTimeout()
és setInterval()
is egy függvényt vár első paraméternek. A stringek replace()
metódusa is opcionálisan tud függvényt fogadni második paraméterként.
Függvényt visszaadó függvények
Az is előfordulhat, hogy a függvény paramétereitől függően más függvényt szeretnénk használni, vagy generálni. Például több számhoz ugyanazt a számot szeretnénk hozzáadni, létrehozhatunk egy függvényt, ami ezt megteszi:
function addNumber(num) {
return function (a) {
// Closure miatt hozzáférünk a num változóhoz.
return a + num;
}
}
// az add10 függvény minden számhoz, amit paraméterként kap, 10-et ad hozzá.
var add10 = addNumber(10);
map([1, 2, 3], add10); // [11, 12, 13]
// Változó bevezetése nélkül, most 100-at adunk hozzá
map([1, 2, 3], addNumber(100)); // [101, 102, 103]
Magasabb rendű függvényekkel kapcsolatban érdemes elolvasni a következőket:
- Eloquent JavaScript - Functional Programming
- Higher-order programming in JavaScript
- Higher Order Javascript
Összefoglalás
Mint láthattuk, a JavaScript nyelvben a függvények működése és használata igencsak összetett tud lenni. Éppen ezért minden esetben gondoljuk át, mikor, milyen formáját használjuk, valamint azt is, hogy milyen környezetben hozzuk létre. Talán kicsit sok is a buktató, viszont egy szépen felépített struktúra sokat tud hozzátenni az áttekinthetőséghez. Remélem ezzel a cikkel sikerült kicsit rendet tenni a fejekben, és többen elkezdenek elmerülni a JavaScript függvények szépségében. További olvasnivalót adhat a témában az MDC és Dmitry A. Soshnikov oldala.
■
Grat!
Szép munka!
Függvények
- nem szeretem az anoním függvényeket, mert hiba esetén a Firebug kb. ennyit ír rá: (?)(), inkább elnevezek mindent valahogy; tudom, kiírja a sor számát, de így már addig is tudok rajta gondolkozni, amíg megkeresem
- többször is előfordult már, hogy egy függvénynek sok paramétert kell átadni, mondjuk hatot, de néha csak az első hármat, néha csak az utolsó előtti kettőt, ami picit nehézkessé teszi a fejlesztést, mert utóbbi esetben meg kell adni az első három paraméter értékét, még ha az undefined is; emiatt én szinte csak objektumokat adok át paraméterként, aztán a függvényben megnézem, hogy mit van benne
- nemrég olvastam egy módszert, hogyan definiáljuk függvényünket úgy, hogy az Singletonként működjön, azaz ne lehessen többször példányosítani:
...
}
Tetszett!
Azon gondolkoztam el, hogy vajon miért csak a new kulcsszó esetén hagyható el a zárójel, ha nem adok át paramétert?
hívás vs érték
y
aFoo
függvényre fog mutatni, azaz utána meg lehet hívniy()
-ként.És más kifejezésben?
Pl. y=foo+2; Szerintem ilyenkor már egyértelmű, hogy meghívni akarom. Tetszene, ha pl. így lehetne használni: objektum.metodusamiobjektumotadvissza.tulajdonsag=20
És a metódus egy tulajdonsága?
Ebben az esetben hogyan érnéd el az objektumot visszaadó metódus egy tulajdonságát? (legyen az prototype vagy más -akár egyedileg definiált- tulajdonság)
Szerintem kár azon a két karakteren spórolni és csökkenteni a kód egyértelműségén. Erre ott vannak a kód miniatürizálók, meg a tömörítés is, ha a méret a lényeg.
Ez inkonzisztens
y=foo+2
kifejezés nem identikus ay=foo()+2
-vel.Persze
JSLint: Missing '()' invoking a constructor.
Ugyanebben a bekezdésben írtad, hogy a zárójel elhagyható, ha a paraméter lista üres lenne. Szerintem itt érdemes lenne megemlíteni, hogy ezt a JSLint nem szereti: Missing '()' invoking a constructor.
Nagyon
Üdv:
Gábor
Bárhogy nézem nem tudok semmi
Like!
Like alternatíva
Ha már egyszer van egy ilyen egyedire alakított Drupal-unk és itt van minden kommentelőnek account-ja, akkor adja magát a megoldás a like-olásra.
Kellene csinálni egy olyan lehetőséget, hogy egy téma kedvencnek jelölhető. A DB-ből ki lehet olvasni, hogy hány embernél van kedvenc témának megjelölve. Ez is egy like megoldás és talán sokkal értelmesebb, mint a FB like; szerintem.
A kedvencnek jelölt topic-okat pedig lehetne minden user-nél listázni, így akár egymás adatlapján lehetne látni, hogy ki mi iránt érdeklődik, mely lehetőséget adna arra, hogy akár kisebb munkacsoportok alakuljanak a hasonló érdeklődésű tagok között, stb, stb.
Modul
Mindezek úgy volnának igazán
Ezt támogassák az említett modulok?
Szerény véleményem szerint, bármi lehet, csak ne egy újabb nagytestvér aki figyeljen.
Légyszi az ilyen, Weblabort
callee, caller
A callee helyett miért kéne
(A caller meg ha jól tudom nem támogatott.)
... az arguments.callee pedig
Csak ezért kérdeztem, gondoltam akkor van helyette valami jobb módszer ha az aktuális függvényre akarok hivatkozni.
De akkor a függvény belsejében nincs mód arra hogy kiderítsem melyik függvény hívta anélkül hogy paraméterként adnám át?
Hát hivatkozhatsz rá a
Arra eddig sem volt mód, hogy kiderítsed, hogy mi hívta. A caller nem cross-browser tulajdonság. Egyébként meg ezek felesleges dolgok, mmint okés, hogy még rugalmasabbá lehet tenni egy kódot velük, de amúgy a gyakorlatban nem túl hasznosak.
Ami gyakorlati szempontból fontos az a függvényt visszaadó függvények, ezeknél meg nincs szükség az arguments.callee-ra. Debughoz meg van backtrace, meg ezer más dolog.
caller
Arra szolgált az
arguments.caller
.Ha jól értem, akkor a strict
Nem
arguments.caller
searguments.callee
. Ezért (is) érdemes kerülni a használatukat. Amennyiben valamiért mégis tudnia kell egy függvénynek egy másik függvényről, akkor azt kapja meg paraméterként.Jó, akkor mégis jól tudtam.
Nekem az a tapasztalatom, hogy az arguments.callee és az arguments.caller teljesen feleslegesek. Az arguments meg simán lehetne tömb is objektum helyett (legalább nem kellene átkonvertálni a tömb metódusok használatához).
Ami nekem nagyon hiányzik ebből a nyelvből az az Object kulcsos Map. Ha lenne olyan Map, amiben a kulcsok DOM Node-k, akkor a jelenlegi gányolt böngészős megoldásokat lehetne egységesíteni egy node-k feletti felületben. Sajnos ilyen nincsen, és nem is lehet lérehozni (legalábbis msie-ben nem, a többi böngészőben igen). :S MSIE-vel az a legnagyobb para, hogy egyik DOM-al kapcsolatos objektum sem leszármazottja az Object-nek, és mivel nem Object-ek, ezért nem lehet property-ket lekérni vagy beállítani rajtuk.
szerk:
Tévedtem, még nagyon régi anyagaim között találtam egy htc-s megoldást, amivel az msie HTMLElement bővíthető. Ezzel már be lehet állítani a hashCode metódust a HTMLElement-re. Részben megoldható a probléma, viszont csak olyan elemekre használható, amiknek lehet style tulajdonsága.
Most fogalmam nincs, hogy
MSIE-vel van olyan, hogy
Az arguments.callee a
Leírtam
Valamint az
arguments.callee
ésarguments.caller
használata nehezebbé teszik a JavaScript motorok belső optimalizálását. Legalábbis amit hallottam tesztek ezt bizonyítják.fúbaz
Baris, kutyás?
js metaprogramozás
Üdv:
Gábor
wow
talán érdemes még megemlíteni a bind-ot, mert akkor ilyet is lehet írni:
"Függvényt visszaadó
Nem csak felhasználási mód
Azt is szabványba tehetnék,
arguments.caller
Lenne egy kérdésem: az arguments.caller helyett létezik valami alternatív megoldás? Írtad, hogy elavult. Esetleg lehet, hogy nem lesz mindig támogatott? Most jött az ötlet, hogy valami hibakereső rendszert lehetne írni a Function.prototype-ba amit pl egy try/catch blokkban elkapunk és vissza követünk, de ha nem tudok hivatkozni a függvényt meghívó függvényre akkor le is mondok róla. Ez csak minap jutott eszembe, és érdekelne valami szakvélemény.
Igen
debugger
kulcsszó, ami ekkor a debug rendszeren ki fogja írni hol tart a kód aktuális futása, valószínűleg teljes stack trace-szel (legalábbis a Firebug, a Chrome és a Safari fejlesztői eszköze ezt csinálja).