ugrás a tartalomhoz

Utólag létrehozott getter nem adja ki a privát változót

zzrek · 2008. Jún. 14. (Szo), 02.15
Sziasztok!
Érdekes jelenségre bukkantam, és szeretnék belőle tanulni (de sajnos megakadtam).
Kezdjük a kóddal, ami egyszerű:

<html>
 <head>
  <title>teszt</title>
  
<script type="text/javascript">

kk=new function()
{
  this.alma=55;
  var korte="körte";
  this.get=function(a)
  {
   return eval(a);
  }
}

alert(kk.get("this.alma")); //55
alert(kk.get("korte")); //körte

kk.get2=function(a)
  {
   return eval(a);
  }
  
alert(kk.get2("this.alma")); //55
alert(kk.get2("korte")); //hiba!!! nincs definiálva!?

</script>
  
 </head>
 <body>

</body>
</html>

Vagyis: a get2 esetében látszólag helyes a futási környezet, mert a "this" működik. Viszont a privát változót nem éri el. Ez miért van így? Meg lehetne valahogy csinálni, hogy az utólag létrehozott függvény olvassa a privát változót is? (Ezek szerint különbözik a "this" érvényessége és a scope működése? Ez miért jó?)
(Próbáltam mindenhogy, sehogyan sem ment...)
Köszi!
 
1

Szerintem...

Ustak · 2008. Jún. 14. (Szo), 08.42
Javítsatok ki, ha tévedek, de a helyzet itt az, hogy a

 var korte="körte";
lokális változó "closure" (Zárlat:-)) miatt érhető el a belső hívó függvényből. Mikor új függvényt deklarálsz, akkor nem történik más, mint egy új objektumot adsz a már létezőhöz, mely épp Function constructorral bír, de ennyi erővel lehetne Array vagy String is, magyarul hiába használod a prototype-láncot, vagy akár a fenti próbálkozást, az újonnan hozzáadott függvényed csak a this-el ellátott változókat fogja látni, és nem lesz Zárlatos, tehát nem fogja észrevenni a régi lokális változókat.
Majd egyszer jobban utánanézek ennek, és írok róla egy cikket. Love metaprograming :-)
2

Closure magyarul

Török Gábor · 2008. Jún. 14. (Szo), 10.11
Ezt a zárlat kifejezést felejtsük el, nem kívánok ebben a szálban terminológiai vitát indítani, de a zárlat abszolút hülyeség, zárványként olvastam már több helyütt, aminek több értelme is van, de megmaradhat closure-nak, és akkor mindenki tudja miről van szó. (Ezt a kérdést kérem új témában folytatni, ha valaki vitatkozna.)
3

Akkor legyen Closure :)

Ustak · 2008. Jún. 14. (Szo), 16.06
Hülyeség de bohókás!
Visszatérve a témára, utánanéztem, és igazam van, a Closurat később nem lehet szimulálni :)
Viszont ez egyben elég memóriaigényes dolog is, mert minden var -nál új foglalás történik példányosítás alatt a memóriában.
Ha már nagyon privát metódus akarsz javaslom a
this.___jajjdeprivatvagyok="Privát Vagyok";
eljárást, ami
"private methods using naming conventions"
néven fut az angol szakirodalomban.
Ha javascript ojjektum-orientált programozással akarsz foglalkozni, először szerintem felejts el mindent, amit az ojjektum orientált programnyelvekről feltételezel :-) Egyébként szerintem nagyon nagyon jó kis nyelv, és nagyon trükkös dolgokat el lehet vele írni. Love metaprogramozás :)
4

köszi

zzrek · 2008. Jún. 14. (Szo), 21.37
Igen én is sejtettem hogy a closure miatt van így, de reménykedtem, hogy a "futási környezet" egyezősége azt jelenti, hogy 2 ugyanolyan függvény ugyanabban a futási környezetben ugyanazokat ér el, ugyanazt hajtja végre. Szeretem én is a javascriptet és azt, hogy ennyire testreszabható, ("metaprogramozható") és szerettem volna a kérdésemre megoldást találni. Most valami egyéb trükkön gondolkodom, amivel mégis el lehet talán érni, hogy ha egy objektumot bővítek egy eljárással, akkor az ugyanolyan lehetőségekkel rendelkezzen, mint azok az eljárások, amik a létrehozásakor már benne voltak.
Köszi a válaszokat, ha van valakinek ötlete, szívesen veszem.
5

scope, this stb

toxin · 2008. Jún. 14. (Szo), 23.31
továbbra is http://jibbering.com/faq/faq_notes/closures.html, egyébként szvsz
           myFooObj = new function fooObj(){
                var foo = "gotcha";
                this.foo = "foo";
                
                this.get = function(variable){
                    return eval(variable);
                };			
                            
                this.addGetter = function(method,getter){
                    this[method] = function(variable){
                        return getter(eval(variable));
                    };
                };				
            };
            
            alert(myFooObj.get('this.foo'));
            alert(myFooObj.get('foo'));
            
            myFooObj.addGetter('get2',function(variable){
                return variable;
            }); 
            
            alert(myFooObj.get2('this.foo'));
            alert(myFooObj.get2('foo'));
maximum trükközgetni lehet vmi hasonlóval

üvd Csaba
6

Ez jó!

Ustak · 2008. Jún. 15. (V), 07.39
ez is jó, bár én úgy csinálnám, hogy lenne egy (vagy több) this.getter függvény, mely closure-segítségével elérné a változókat és utána későbbi prototype-hoz hozzáadott függvényekkel ezt (ezeket) használnám.
Az eval-t minden szakirodalom elkerülendőnek jelzi...én még sosem használtam, van ennek valóságalapja?
7

Tévedtem....

Ustak · 2008. Jún. 15. (V), 07.43
a jquery-ben van eval, tehát átvitt értelemben használtam, csak saját kódhoz nem. Csak leírom mielőtt megköveztek :-)
8

eval

toxin · 2008. Jún. 15. (V), 09.49
The eval form is much harder to read. This form will be significantly slower because it needs to run the compiler just to execute a trivial assignment statement. It also frustrates JSLint (see Appendix C), so the tool's ability to detect problems is significantly reduced.

The eval function also compromises the security of your application because it grants too much authority to the eval'd text. And it compromises the performance of the language as a whole in the same way that the with statement does.
- JavaScript: The Good Parts by Douglas Crockford
Publisher: O'Reilly
Pub Date: May 2, 2008
Print ISBN-13: 978-0-596-51774-8


JSON parse-oláson kívül másra nem szoktam használni, lehet vele még töréspontot rakni a kódba:

           var __bind__ = function(f,s){ return function(){ return f.apply(s,arguments); }}; 
            
            function inspect(inspector){				
                while(expression = prompt("gimme an expression:")){
                    alert(inspector(expression));
                };
            };
                                
            var myFooObj = new function fooObj(){
                var foo = "gotcha";
                this.foo = "foo"; 
                inspect(__bind__(function(__debug__){
                    try {
                        return eval(__debug__);
                    }catch(e){
                        return "not found";
                    }					
                },this));              				
            };           
:)

üdv Csaba
9

ha van eval, minden van

zzrek · 2008. Jún. 15. (V), 10.23
Igen és is próbálgattam ilyesmivel, de persze ha már van "zárványolt" evalozási lehetőség, akkor minden van (az addGetter is helyettesíthető vagy akár létre is hozható utólag):

  myFooObj.get("this.get3=function(a){return eval(a)}");

  alert(myFooObj.get3('this.foo'));
  alert(myFooObj.get3('foo'));
De a lényeg, ami a korlátot jelenti, hogy ezek szerint "örökölt" függvények nem képesek úgy működni, mind az előre definiáltak, sajnos:

Object.prototype.barmiNovelo_o = function(variableName){
          return eval("++"+variableName);
}

 myFooObj = new function fooObj(){
      var foo = 11;
      this.foo = 22;

      this.barmiNovelo = function(variableName){
          return eval("++"+variableName);
      };

      alert(this.barmiNovelo("this.foo")); //23
      alert(this.barmiNovelo("foo")); //12
      alert(this.barmiNovelo_o("this.foo")); //24
      alert(this.barmiNovelo_o("foo")); // hát ez nem megy

  };
És nemcsak az evalolásról van szó, hanem semmiképp sem működik: nem tudok olyan függvényt örököltetni, ami konstruáláskor vagy később lokális privát változót használ.
10

nem

toxin · 2008. Jún. 15. (V), 11.07
javascript alatt, csak szimulálni lehet a privát változókat, általában _változóNév, _metódusNév -ként szokás őket bevezetni, és kódolás közben tartani magad hozzá
           var o = {
                
                publicVar : false,				
                _privVar : 'privát',
                
                method1	: function(){
                    return this._privVar;
                }								
            };
            
            o.method2 = function(){
                alert(this._privVar)	
            };
            
            o.method2();
privát lokális változók pedig nem örökítésre, hanem http://javascript.crockford.com/private.html valók

üdv Csaba
11

mindegy

zzrek · 2008. Jún. 15. (V), 11.38
Nekem most teljesen mindegy, hogy minek hívják és hogy mire illik használni. Ha mondjuk egy keretrendszert szeretnék létrehozni, akkor jobb lenne, ha a felhasználóknak nem kéne magyarázni, hogy ne használjanak "var"-ral deklarált változókat, mert azt képtelen kezelni a keretrendszer. (persze meg lehet oldani mindent máshogy is, csak most épp ebbe a problémába botlottam és jó lett volna, ha valahogy egyszerűen meg lehetett volna oldani. Enélkül nem lehet pl. tetszőleges objektumot serializálni, és gond lehet a callback függvényekkel is, stb.)
A "var" lokális változók használata vagy haszna (hogy hogyan "illik" használni) az pont a closure lehetősége miatt ellentmondásos: a closure lehet egy hasznos eszköz, de utólag nem bővíthető tetszőlegesen egy objektum, csak akkor ha már a konstrukciós fázisban erre felkészítettük. Ez azért egy jelentős korlát. (tekintve, hogy a javascript egyébként nagyon "szabad" környezetet ad, kár hogy ez nem lehetséges)

Egyébként köszi, jók a linkek is, most olvasgatom...