Komentáře k článku
Do hlubin implementací JavaScriptu: 3. díl – výkonnostně nepříjemné konstrukce

V dnešním dílu seriálu zakončíme obecné povídání o rychlosti interpretace JavaScriptu. Podíváme se na funkci eval, dále na to, jak výkonnostně nepříjemná může být možnost zjistit informace o parametrech funkcí na zásobníku a také na příkaz with. Na závěr si stručně povíme, jak jsou interprety obvykle implementované.
RE: Do hlubin implementací JavaScriptu: 3. díl - výkonnostně nepříjemné konstrukce
mate to nejak overene, nebo to je jen domenka?
v pripade, ze jednotlive identifikatory jsou sdilene (coz je vcelku trivialni optimalizace), pak rozdil mezi pouzitim indexu a prohledavanim tabulky lokalnich promennych je radove v jednotkach instrukci daneho stroje, coz pro vetsinu rozumnych programu funkce ma (< 10 promennych/parametru) predstavuje zrychleni na urovni statisticke odchylky (+ samozrejme neco sezere jeste staticka analyza)
RE: Do hlubin implementací JavaScriptu: 3. díl - výkonnostně nepříjemné konstrukce
Ověřené to nemám, své tvrzení jsem asi měl formulovat trochu opatrněji.
RE: Do hlubin implementací JavaScriptu: 3. díl - výkonnostně nepříjemné konstrukce
Stalo by za to ujasnit, co znamena podle vas v JS lokalni promenna, globalni promenna a parametr. Vse se sice zda trivialni, ale co treba rozebrat takovy priklad:
function base(a)
{
var b = 4;
return function sum()
{
return a + b;
}
}
var a = 3;
a = sum();
var sum = base(4);
a = sum();
RE: Do hlubin implementací JavaScriptu: 3. díl - výkonnostně nepříjemné konstrukce
V článku popisuju konrétní situaci v toplevel funkci, tam ten identifikátor může skutečně být jen globální (= toplevel) proměnná nebo lokální proměnná či parametr (technicky je to totéž).
Ve složitější situaci je samozřejmě třeba uvažovat celý lexikální scope chain. Jako lokální proměnnou bych pak definoval proměnnou zaznamenanou v posledním článku aktuálního scope chain, jako globální proměnnou proměnnou zaznamenanou v článku prvním. Jestli existuje nějaký používaný pojem i pro proměnné definované v ostatních článcích, netuším.
K příkladu: V ECMA-262, 3. edice, sekce 13 se píše, že funkční výraz (to, co vracíte ve funkci
base
) nezapisuje název funkce jako identifikátor do aktuální tabulky proměnných (do posledního článku scope chain) a už vůbec ne do tabulky globálních proměnných (do prvního článku scope chain), a nelze se na něj tedy odvolávat v toplevelu. První příkaza = sum();
tedy vyhodí chybu.Pokud bychom ho odstranili, tak na posledním řádku bude mít globální proměnná
sum
hodnotu funkce vracené vbase
, která bude mít díky uzávěrové vlastnosti poznamenán schope chain, kdea
byla proměnná v jeho předposledním článku (tj. ani globální, ani lokální proměnná dle mé definice) a měla hodnotu4
. Po zavolání druhého příkazua = sum();
bude tedy hodnotaa
rovna8
.Doufám, že vás to přesvědčilo, že vím, o čem mluvím :-)
RE: Do hlubin implementací JavaScriptu: 3. díl - výkonnostně nepříjemné konstrukce
No je možné z funkcie vrátiť vnorenú funkciu ako objekt.
Nižšie som dal príklad (22.2).
Môžete posúdiť, ako by to bolo vtedy s optimalizáciami?
caller
Pokial viem, tak caller je depricated https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments/caller a myslim, ze som to videl napisane aj v Referncnej prirucke Javascriptu.
Je pravda, ze eval je nielen nebezpecny, ale aj komplikuje chod kodu, ale niekedy je to jedina moznost. napr. spracovanie JSON a podobne veci.
Re: caller
Pokud zpracovavam JSON data prichazejici pres AJAX, tak me, vzhledem k odezve serveru, zpomaleni evalem moc nezajima :) Ale jinak se mu vyhybam, znecitelnuje kod a tim je i zdrojem chyb (spousteny kod v promenne? mfg).
Re: caller
Pozor, je rozdíl mezi
arguments.caller
aFunction.caller
. První je opravdu deprecated/obsolete, druhé „jen“ nestandardní rozšíření.Re: caller
A nejblbější je, že Opera na obě varianty hází bobek jako jediná. Takže kdo chce psát objektově s dedičností v JS tak to musí šíleně obcházet. Kdyby to radši uzákonili v nějaký normě bylo by vše mnohem jednodušší.
Re: caller
V Opere 9.6b bola pridana podpora Function:caller.
Re: caller
Jak souvisi Function.caller nebo arguments.caller s objektovym programovanim a dedicnosti v JS?
Re: caller
Pokud chceme implementovat funkci volani metody predka rekurzivne (avsak stale v kontextu nejake konkretni instance), je nutne "kamsi" ukladat referenci na tridu, jejiz metodu prave volame (to proto, aby bylo mozne pri dalsim volani predka "postoupit vyse" k predchozi tride). Vhodne misto k tomuto je napr. staticka vlatnost volane metody. Abychom se z teoreticky funkce "callSuperMethod" dostali k teto vlastnosti, potrebujeme mit prave arguments.caller (tj. referenci na funckci, ze ktere jsme volani). Pripadnou diskuzi na toto tema doporucuji presunout do urovne e-mailove korespondence s priklady, protoze v teto diskuzi je obtizno pokracovat bez konkretnich ukazek.
Eval a alternativy
Jaké jsou tedy možnosti jak eval obejít? Možná by nebylo od věci pár typických příkladů rozebrat, protože ono se té funkce občas zbavuje velmi obtížně (samozřejmě je to často i o pohodlnosti).
Re: Eval a alternativy
jeden priklad pro vyse zmineny JSON:
zle:
v = eval(jsonsrc)
dobre:
<script type="text/javascript">
v = jsonsrc
</script>
(jde to nahradit v iframe "ajaxu", pro xmlhttprequest uz to nepujde)
(taky to jde pouzit pro "boot" volby, konfigurace a pod.. generovane serverem pri startu aplikace)
Re: Eval a alternativy
O JSON, nepoužívání eval a lepších variantách tu máme dokonce malý seriál 8-)
http://zdrojak.root.cz/serialy/json-pro-vymenu-dat-na-webu/
Re: Eval a alternativy
Tak pro parsování JSON by se eval stejně neměl používat – raději JSON parser, ale to hlavně z bezpečnostních důvodů (eval je v tomto případě rychlejší). Jinak já bych odpověděl protiotázkou – k čemu eval vůbec potřebujete? Já jsem jej snad nikdy seoriózně nepoužil.
Díky
Já chci jen poděkovat za dobrý článek. Od té doby, co root tak nějak zmainstreamovatěl už tam vývojářské věci nikdo moc nepublikuje. Proto díky za sekci zdroják a za zajímavé povídání o javascriptu.
Re: Díky
+1
Je v tomto výkonovo nejaký rozdiel?
var id1 = function(){var n = 0; return function(){return n++;};}();
with({n:0}) var id2 = function(){return n++;};
// Je výkonovo nejaký rozdiel medzi id1 a id2, prípadne čo sa týka optimalizácií?