Volanie funkcie odovzdanej referenciou s odovzdaním argumentov – JavaScript, AJAX, jQuery – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Volanie funkcie odovzdanej referenciou s odovzdaním argumentov – JavaScript, AJAX, jQuery – Fórum – Programujte.comVolanie funkcie odovzdanej referenciou s odovzdaním argumentov – JavaScript, AJAX, jQuery – Fórum – Programujte.com

 

Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
Prog.0
Věrný člen
18. 10. 2007   #1
-
0
-

Chcem aby moja funkcia zavolala druhú a vrátila jej výsledok. Chcem tiež aby jej odovzdala rovnaké parametre.
Asi takto:

my_fn()        zavolá a vráti výsledok my_fn2()

my_fn(a,b,c) zavolá a vráti výsledok my_fn2(a,b,c)
my_fn(a,b,c,d) zavolá a vráti výsledok my_fn2(a,b,c,d)

..v skratke, neviem koľko parametrov budem odovzdávať, ale chcem, aby sa poslali ďalej do konkrétnej funkcie. Takto budem chcieť prepojiť viacero funkcií, takže som na to šiel takto:
var my_fn = function() 

{
return _fn_call( 'my_fn2' , arguments );
// _fn_call bude fcia, ktorá prijíme dva parametre:
// prvý = názov fcie, ktorá sa má zavolať
// druhý = pole obsahujúce predané argumenty

};

var _fn_call = function( fn_name , args_array )
{
// vytvorí srtingový výraz, ako by sa mala fcia zavolať
// a odovzdá ho fcii eval()

var i, args = [];
for( i=0 ; i<args_array.length ; i++ ) args.push( 'args_array[' + i + ']' );
return eval( fn_name + '(' + args.join( ',' ) + ')' );
}

Čiastočne to funguje. Problém je, že sa to picha do stringu, a nakoniec tá fcia eval... proste humus. Vedel by sa to prekusnúť, keby som takto nepotreboval volať funkcie z iného scope. To znamená že chcem odovzdávať cieľovú funkciu referenciou, a nie stringovým názvom fcie. Asi takto:
var my_fn = function() { return _fn_call( my_fn2 , arguments ) };


// šlo by to potom aj anonymne (vedľajší produkt)
var my_fn = function() { return _fn_call( function() { ... } , arguments ) };

Ja ale teraz neviem napísať fciu _fn_call pre dopredu neznámy počet argumentov. Nedá sa to ani pichnúť do evalu. Viem len niečo takéto:
var _fn_call = function( fn_ref , args )

{
switch( args.length )
{
case 0: return fn_ref( );
case 1: return fn_ref( args[ 0 ] );
case 2: return fn_ref( args[ 0 ], args[ 1 ] );
case 3: return fn_ref( args[ 0 ], args[ 1 ], args[ 2 ] );
...
}
};

...aj keď to je ešte vačší humus ako pred tým, funguje aspoň to odovzdávanie referenciou. Nevýhoda je konečný počet argumentov.

Nepozná niekto nejaké pekné riešenie ? (vopred ďakujem ;-)

Nahlásit jako SPAM
IP: ...–
Prog.
Reklama
Reklama
Prog.0
Věrný člen
18. 10. 2007   #2
-
0
-

don_Dominique:
Proc prostě v my_fn() nezavolat podle poctu paramtů rovnou tu my_fn_2(); ?


lebo to píšem všeobecne, a sám ešte neviem, aké a koľko parametrov bude prijímať, resp. bude prijímať rôzny počet parametrov.

mohol by som:
function my_fn()

{
switch(arguments.length)
{
case 0: return my_fn2();
case 1: return my_fn2( arguments[0] );
case 2: return my_fn2( arguments[0], arguments[1] );
...
}
}

function my_other_fn()
{
switch(arguments.length)
{
case 0: return my_other_fn2();
case 1: return my_other_fn2( arguments[0] );
case 2: return my_other_fn2( arguments[0], arguments[1] );
...
}
}


...lenže takých fcii budem všeobecne definovať asi viac, a bol by to pekný bordel, navyše, stále je tam ten konečný počet argumentov, čo by sa tiež dalo prekusnúť a prispôsobiť každú fciu na všetky možnosti akými sa zvykne volať (ale bola by to babračka)...

Nahlásit jako SPAM
IP: ...–
Prog.
Prog.0
Věrný člen
18. 10. 2007   #3
-
0
-

Ach jo, nakoniec pomohlo trocha šťastia pri googlení.

var my_fn = function() { return my_fn2.apply( my_fn2 , arguments ) };

resp.:
var my_fn = function { return _fn_call(my_fn2,arguments) };

var _fn_call = function(fn,arg)
{
return fn.apply( fn , arg );
}


[podtrzene]ECMA-262 Edition 3[/podtrzene]

15.3.4.3 Function.prototype.apply (thisArg, argArray)

The apply method takes two arguments, thisArg and argArray, and performs a function call using the [[Call]] property of the object. If the object does not have a [[Call]] property, a TypeError exception is thrown. If thisArg is null or undefined, the called function is passed the global object as the this value. Otherwise, the called function is passed ToObject(thisArg) as the this value. If argArray is null or undefined, the called function is passed no arguments. Otherwise, if argArray is neither an array nor an arguments object (see 10.1.8), a TypeError exception is thrown. If argArray is either an array or an arguments object, the function is passed the (ToUint32(argArray.length)) arguments argArray[0], argArray[1], …, argArray[ToUint32(argArray.length)–1].
The length property of the apply method is 2.

Nahlásit jako SPAM
IP: ...–
Prog.
Petroff0
Věrný člen
18. 10. 2007   #4
-
0
-

str=arguments.join(","); // kupodivu funguje také pop & shift v Opeře ,kdežto IE >> objekt nezná tuto metodu

Jinak mám návrh: zkoušel jsi ?
function zpracuj() {zpracuj.akce.apply(this,arguments)}

function priklad1(a,b,c,d){for(var R,S=" Argumenty: ",i=-1; R=arguments[++i];) S+="["+R+"]"; alert(S)}
function priklad2(a,b,c,d) {while (arguments.length) alert(arguments.pop())}

zpracuj.akce=priklad1; zpracuj(11,22,33,44);
zpracuj.akce=priklad2; zpracuj(11,22,33,44);


Nahlásit jako SPAM
IP: ...–
Petroff0
Věrný člen
18. 10. 2007   #5
-
0
-

A hele, zatímco jsem dumal, je kápnuto. Oba ve stejnou chvíli.
Akorát to moje funguje asi jen v Opeře (nemám převedený obj. Arguments na Array), teda IE se nechytá....
Grat...petr

Nahlásit jako SPAM
IP: ...–
Prog.0
Věrný člen
20. 10. 2007   #6
-
0
-

To Petroff:
Ďakujem za ochodu aj úsilie, nakoniec sa mi to podarilo rozkusať :-)

inak mám návrh: zkoušel jsi ?
function zpracuj() {zpracuj.akce.apply(this,arguments)}

...no, keby som poznal tú metódu apply, tak by som ju skúsil :-)

...kdežto IE >> objekt nezná tuto metodu...

IE, ani zvyšok ma nezaujíma, bude to extension do Mozilly...

Jou, a ešte ďakujem za jednu vec (práve teraz ma napadla). Keďže tá fcia zpracuj by bola stále rovnaká, záležalo by len od jej .akce, tak má to inšpirovalo k niečomu takému:
var my_fn1 = _prepoj( my_fn1_2 );

var my_fn2 = _prepoj( my_fn2_2 );

var _prepoj = function( fn )
{
var args = arguments;
return function() { fn.apply(fn,args) };
}

...dúfam že to bude fungovať, prípadne sa s tým ešte pohrám :-)

Nahlásit jako SPAM
IP: ...–
Prog.
Prog.0
Věrný člen
20. 10. 2007   #7
-
0
-

Oki, chybyčka sa vloudila, neviem prečo som tam chcel tie argumenty ťahať z tej vyžšej fcie :-)
A druhá vec, keď uvediem thisArg = fn, tak to nejde, nezisťoval som prečo, hodil som tam null, a beží to... zatiaľ ma to netrápi. Problém by asi mohol nastať keby som robil niečo také:

my_class2 = function()

{
this.pokus = 'pokus';
}
my_class.prototype.skus = function() { alert(this.pokus) };
var my_class = _prepoj(my_class2);

var test = new my_class();
test.skus();
...momentálne nemám čas sa až tak sa s tým hrať, možno to pojde aj s null.

Jou, a opravená fcia _prepoj:
var _prepoj = function( fn )

{
return function()
{
fn.apply(null,arguments);
}
}


Ešte raz, ďík ;-)

Nahlásit jako SPAM
IP: ...–
Prog.
Petroff0
Věrný člen
23. 10. 2007   #8
-
0
-

...momentálne nemám čas sa až tak sa s tým hrať, možno to pojde aj s null.


Nejede - hází to undefined.
Pokud použiješ this, tak se chová správně:
var TArray = function(){ while(arguments.length) this.unshift(arguments.pop()) }

TArray.prototype = new Array();

/* Funguje? */ var xx=new TArray(11,222,3333,444444); alert(xx);
/*************************************************************************/
var _prepoj=function(fn) { return function(){fn.apply(this,arguments)} }
/*************************************************************************/

var TWeek = _prepoj(TArray);

TWeek.prototype=new Array();
TWeek.prototype.showDay = function(n){ alert (this[n-1]); }

var test = new TWeek("pondeli","utery","streda","ctvrtek","patek","so","ne");
test.showDay(1);
test.showDay(3);
test.showDay(6);
test.showDay(7);


Pochopitelně jsem to netestoval ve složitých oborech, ale v PROTOTYPE.JS se používá podobně:
var Class = {

create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}


Nahlásit jako SPAM
IP: 89.102.211.–
Prog.0
Věrný člen
24. 10. 2007   #9
-
0
-

Uf, tak som na to mrkol, no nebolo to presne to, čo som chcel:

arguments.pop() mi nefunguje (teraz to nieje podstatné) tak som to prepísal asi takto:

  var TArray = function()

{
for(var i=0;i<arguments.length;i++)
{
this.push(arguments[i]);
}
}
TArray.prototype = new Array();
teraz som doplnil:
  TArray.prototype.show = function( index ) { alert(this[index]) };
A toto už nefunguje:
  var TWeek = _prepoj(TArray);

var test = new TWeek("pondeli","utery","streda","ctvrtek","patek","so","ne");
Vyhodí chybu vo funkcii TArray(), pretože this.push teraz neexistuje, keďže this, ktorý bol odovzdaný funkciou _prepoj "je trocha mimo", ukazuje na objekt anonymnej funkcie, ktorá sa returnuje vo funkcii _prepoj.

Znova som upravil fciu _prepoj, tak aby vytvorila novú funkciu - objekt, a skopírovala mu prototype od originálnej fcie:
  var _prepoj=function( fn ) 

{
var result = function()
{
fn.apply(this,arguments)
}
if (fn.prototype) result.prototype = fn.prototype;
return result;
}


Teraz mi to funguje takto:


// TEST 1:
var msg = _prepoj(alert);
msg('pokus');

// TEST 2:
var TArray = function() { for(var i=0;i<arguments.length;i++) this.push(arguments[i]) };
TArray.prototype = new Array();
TArray.prototype.show = function( index ) { alert(this[index]) };

var TWeek = _prepoj(TArray);
TWeek.prototype.showDay = function( n ) { return this.show( n-1 ) };

var test = new TWeek("pondeli","utery","streda","ctvrtek","patek","so","ne");

test.show(0); // "zdedená/prepojená" metóda od TArray
test.showDay(1); // vlastná metóda TWeak


Nahlásit jako SPAM
IP: 213.160.186.–
Prog.
Petroff0
Věrný člen
26. 10. 2007   #10
-
0
-

arguments.pop() mi nefunguje (teraz to nieje podstatné) tak som to prepísal . . . . .


arguments.pop is not a function => hláška z FF2
Já jsem to testoval v Opeře a tam byla celá ukázka 100% funkční
....zapomněl jsem že pracuješ v Mozille, FF jsem ani jednou nepoužil a nenapadlo mě když jsem konstatoval,že IE se nechytá, že je to jinak:
chytá se pouze Opera - nebo spíš poskytuje "nadstandard" (oproti ECMA specifikaci)

Hlavně z ní bylo vidět, že je nutno TWeek.prototype=new Array(); po _prepojení obnovit (a udělat to ještě před voláním constructoru var test=new TWeek(1,2,3.....7))

Paráda, zdá se, že už je to dokonalé - 2 závěrečné testy (tentokrát ve Firefoxu :smile1: :
// TEST 1+2:

function fn_pohnout(x,y){window.resizeBy(x,y)};
function fn_napsat(a,b,c,d,e){document.write(a||"",b||"",c||"",d||"",e||"")};

var msg = _prepoj(alert);

msg('pohni');
fn_pohnout(window.resizeBy,-111,-111); /* opět Opera jako jediná.. . . . . . .tentokrát nefunguje */
msg('napis');
fn_napsat("Forum ","mi ","pije ","krev.");
msg('pohni');

var nazpatek = _prepoj(window.resizeBy);
nazpatek(111,111);
msg('napis');

var napravit = _prepoj(document.write);
napravit("Nic ","neni ","dokonale.");

Nahlásit jako SPAM
IP: 89.102.211.–
Prog.0
Věrný člen
27. 10. 2007   #11
-
0
-

Jop, Firefox sa zachoval spravne, Opera robí veci navyše :-)

http://developer.mozilla.org/... http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Functions:arguments#Description

...The arguments object is not an array. It is similar to an array, but does not have any array properties except length. For example, it does not have the pop method. However it can be converted to an real array:

var args = Array.prototype.slice.call(arguments);



..Hej, je to fajn, teraz sa to dá používať aj na dedičnosť :-)

Nahlásit jako SPAM
IP: 213.160.186.–
Prog.
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 15 hostů

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý