Javascriptový problém: pojmenování obsahu pole [příspěvek v archivu]
Narazil jsem na docela zajímavou otázku v Javascriptu a zajímalo by mě, jak takovou věc co nejelegantněji vyřešit. Řekněme, že mám funkci, která od nějkaého cizího externího zdroje dostává jediný parametr, který je pole. Pořadí a význam jeho položek jsou pevně dány, délka pole je proměnná (nemusí být uvedeny všechny definované položky) a podobu a způsob předávání toho parametru nemohu nijak ovlivnit. Otázka zní, jak co nejlépe načíst toto pole tak, abych na jeho položky nepřistupoval přes indexy, ale přes nějaká smysluplná jména.
V PHP to udělám snadno:
list($jmeno,$prijmeni,$datum,...,$status) = $arr;
V Javascriptu ale (pokud vím) podobný konstrukt není. Úplně nejpitomější řešení je nasnadě:
function X(arr) {
var jmeno = arr[0];
var prijmeni = arr[1];
var datum = arr[2];
// ...
var status = arr[arr.length-1];
// ...
alert(prijmeni);
}
Což je vážně docela hloupé. Malinko lepší (nebo spíš čistší) se jeví přiřazení do objektu:
function X(arr) {
var osoba = {
jmeno: arr[0],
prijmeni: arr[1],
datum: arr[2],
// ...
status: arr[arr.length-1]
}
// ...
alert(osoba.prijmeni);
}
Taky si můžu ty názvy předdefinovat a přiřazení zautomatizovat:
function X(arr) {
var def = ['jmeno','prijmeni','datum', ..., 'status'];
var n = def.length;
if (arr.length<n) n = arr.length;
var osoba;
for (var i=0;i<n;i++) osoba[def[i]] = arr[i];
// ...
alert(osoba['prijmeni']);
}
anebo rovnou jako správný drsoň:
Array.prototype.addKeys = function(def) {
var n = Math.min(def.length, this.length);
for (var i=0;i<n;i++) this[def[i].toString()] = this[i];
}
function X(arr) {
arr.addKeys(['jmeno','prijmeni','datum', ..., 'status']);
// ...
alert(arr.prijmeni);
}
Ale určitě existuje nějaký lepší, elegantnější způsob, jak si ten obsah pole pojmenovat. Napadne někoho něco?
Update: Moc pěkné řešení
Kolega wiki přišel na poměrně elegantní a podle mě vtipné řešení: předat pole, které funkce dostane, jako standardní parametry druhé funkci, která už s nimi bude pracovat normálně. Nejlépe ukázat na příkladu:
function X(arr) {
X2.apply(null,arr);
}
function X2(jmeno,prijmeni,datum,...,status) {
// ...
alert(prijmeni);
}
Podle potřeby bych si to mohl upravit do nějakých sofistikovanějších tvarů, ale princip zůstává. Ve finále by to mohlo vypadat například takhle:
function X(arr) {
(function (jmeno,prijmeni,datum,...,status) {
// ...
alert(prijmeni);
}).apply(null,arr);
}
Má to jen malou mušku v tom, že to funguje až v Javascriptu 1.3, resp. JScriptu 5.5, tedy od IE 5.5 (v 5.0× to chodit nebude), ale to už by dnes nemělo skoro nikoho trápit. Díky moc za supr nápad.
Petr Staníček, 4. 12. 2007 000 20.44 • Rubrika: IT, Všeobecné, Webdesign • 19 komentářů u textu s názvem Javascriptový problém: pojmenování obsahu pole
19 komentářů k článku »Javascriptový problém: pojmenování obsahu pole«
[1] Vložil(a): Martin Hassman 4. 12. 2007 v 23.06
Lámal jsem si hlavu, ale nakonec mi vždy vypadlo řešení podobné některému z těch, co jsi už napsal. Opatrně bych si troufal tvrdit, že tohle současný JavaScript lépe nezvládne (opatrně pro případ, že to někdo v dalším komentáři vyvrátí). Varianta addKeys je zaručeně cool a trendy.
Co tak brousím připravovaným ECMA Script 4 (JavaScript 2) href=„http://www.ecmascript.org/es4/spec/overview.pdf“ rel=„nofollow ugc“>http://www.ecmascript.org/es4/spec/overview.pdf tam už by to mělo jít některou z jeho konstrukcí, ale tě bude zajímat tak za 3–5 let.
[2] Vložil(a): karf 4. 12. 2007 v 23.25
[1] Chtěl jsem zrovna napsat komentář podobného znění, takže jen přitakám. Jen s výhradou vůči přidávání funkce přímo do prototypu Array a se zpochybněním termínu použitelnosti ES4 :(. Ještě mě napadlo využití objektu arguments uvnitř funkce a předávat klíče přímo jako parametry, ale na principu to nic nemění.
[3] Vložil(a): Willik 4. 12. 2007 v 23.57
Nevim jestli jsem spravne pochopil zadani ale od verze JS 1.7 by melo fungovat neco takoveho:
var inArray = [‚jmeno‘,‚prijmeni‘,‚datum‘,‚adresa‘];
var [jmeno,prijmeni,datum,adresa] = inArray;
alert (jmeno + " " + prijmeni + " " + datum + " " +adresa);
[4] Vložil(a): Pixy 5. 12. 2007 v 1.23
[3] Ano, to je přesně ono, co by se mi líbilo. Otázka ale zní: je JS 1.7 implementován taky jinde než ve FF2? Obávám se, že v IE to fungovat nebude (ale pro jistotu vyzkouším).
[5] Vložil(a): Willik 5. 12. 2007 v 1.41
Bohuzel co vim tak v IE6 to nefunguje, coz je dnes jeste problem.
[6] Vložil(a): Willik 5. 12. 2007 v 2.09
Pak bych mel jeste jedno reseni, ale je to trochu pres koleno – protoze IE a Opera nepodporuje forEach tak je nutne upravit prototype pro Array (je to z mozilla.org a jak sem to prolit tak to funguje).
Cele to reseni neni uz tak pekne ale urcite by se dalo pouzit:
[7] Vložil(a): Pixy 5. 12. 2007 v 2.28
[6] … když už bych kvůli té jedné malé funkci měl opravovat prototyp Array, tak tam radši rovnou udělám tu metodu addKeys() a je to.
[8] Vložil(a): aprilchild 5. 12. 2007 v 4.52
V JavaScriptu zadna podobna konstrukce v soucasnosti neni (beru v potaz implementace bezici alespon od IE6). Osobne bych to resil nejak takhle:
[9] Vložil(a): Pixy 5. 12. 2007 v 9.58
ad [6] – trochu buldozer na mravence a hlavně viz [7] – když už se rozhodnu jít do vlastních rozšíření std. objektů, udělám to jednodušeji a efektivněji.
ad [8] – ať koukám, jak koukám, žádný rozdíl oproti tomu namapování, co uvádím v článku, nevidím. Akorát to rozšiřujete o další složitější funkce. To už je málem framework…
Jde fakt o malou jednoduchou funkci a co nejefektivnější pojmenování položek pole, abych při jejich zpracování nemusel pracovat s nicneříkajícími indexy, jako
if (d[11]) x = d[7] + (d[2]?d[3]:d[4]);
atd… Udělat si na to nějaký framework je v tomhle případě to nejsnazší a nejpohodlnější – a nejméně vhodné řešení[10] Vložil(a): Radek 5. 12. 2007 v 10.56
Možná je to nehodné moderního dynamicky typovaného jazyka, ale pro úplnost je potřeba zmínit klasické, historií prověřené řešení:
var P_JMENO = 1;
var P_PRIJMENI = 2;
var P_DATUM=3;
…
if (data[P_JMENO] == data[P_PRIJMENI]) alert(„Jmenujete se divne“)
[11] Vložil(a): Filip Jirsák 5. 12. 2007 v 11.21
Ta PHP funkce se dá přibližně imitovat následujícím kódem:
[12] Vložil(a): Pixy 5. 12. 2007 v 11.29
[11] Jo, to je pěkné! Dík. ;)
Jen bych ještě doplnil do té funkce nějaké testy, protože podle zadání to pole nemusí obsahovat všechny položky a
arr
může být kratší než počet argumentů.[13] Vložil(a): Pixy 5. 12. 2007 v 11.44
Doplnil jsem do článku jedno moc pěkné řešení, podle mě zatím nejlepší.
[14] Vložil(a): Filip Jirsák 5. 12. 2007 v 11.49
[12] Pokud bude pole kratší, zbývající vlastnosti budou mít hodnotu
undefined
, takže všechny běžné testy se k tomu zachovají správně:alert(obj.c == undefined);
alert(obj.c == null);
alert(!obj.c);
alert(typeof(obj.c) == „undefined“);
Jediné, co se bude chovat jinak, je test na samotnou existenci vlastnosti:
alert(„c“ in obj);
Pokud vlastnost, která nemá odpovídající element, nemá vzniknou ani s hodnotou
undefined
, měla by stačit následující úprava:function List(arr) {
for (var i = 0; i < Math.min(arguments.length-1, arr.length); i++) {
this[arguments[i+1]] = arr[i];
}
}
[15] Vložil(a): Willik 5. 12. 2007 v 14.37
To reseni – apply(null,arr); je rozhodne nejlepsi, bezvadnej napad
[16] Vložil(a): Pixy 5. 12. 2007 v 15.11
[15] Bohužel jsem ho před chvílí zkusil použít v jedné aplikaci a v IE6 to nefunguje. Nemám čas teď zkoumat, co je špatně, ale určitě to potřebuje nějaké důkladnější otestování. Podle specifikace by
function.apply()
mělo fungovat od IE 5.5, otázkou je, co s tím udělá ta varianta snull
.[17] Vložil(a): patrik.ovx 6. 12. 2007 v 10.06
[18] Vložil(a): Pixy 6. 12. 2007 v 11.14
[17] To je ovšem pro pořádně drsné jinochy. Narvat do všech objektů v JS natvrdo property „patrik“ a „ovx“… A co kdyby definice vypadala třeba takhle:
def = ['name','id','style','constructor','__proto__']
to by teprve začala správná zábava… Ne, se vší úctou, tohle fakt nepovažuju za dobré řešení, ani kdyby v tom
eval()
místo tohoObject.prototype
bylo (imho správněji)Array.prototype
– i tak je to příliš drsné a extrémně nebezpečné.[19] Vložil(a): patrik.ovx 6. 12. 2007 v 13.40
[18] předpokládám, že šlo o to ukázat cestu. vstup by se měl ošetřit a místo Object by asi šlo napsat this, ale pak jsme zase u řešení p. Jirsáka :)
Předpokládám, že zdatný programátor si to už upraví sám
Nevím o jaké nebezpečnosti u javascriptu mluvíte?
Váš komentář
Upozornění: Pokud vás téma tohoto příspěvku nezajímá, nebaví, dotýká se vás či vás dokonce uráží, tak prosím odejděte a pokud možno se nadále ve vlastním zájmu dalším podobným vyhýbejte. Hlavně se to prosím nesnažte autorovi sdělovat v komentářích, takové příspěvky nikoho nezajímají a budou nejspíš vymazány. Totéž platí pro vaše názory na osobu autora, na jiné přispěvatele, mluvení z cesty, ze spaní či pod vlivem omamných látek a další podobné výlevy nesouvisející s tématem článku. Jinými slovy, toto je prostor soukromého blogu určený pro komentování příspěvku publikovaného výše, nikoli k chatování a volné diskusi. Děkuji za pochopení.
Abyste mohli komentovat, musíte se přihlásit.