ugrás a tartalomhoz

OOP Callback, this?

deejayy · 2012. Dec. 30. (V), 02.09
Sziasztok,

röviden nem tudnám leírni a JavaScript problémámat, bár biztosan van rá valami szakkifejezés, tehát inkább kifejtem:

Kreáltam egy objektumot imigyen:
  1. function myObject(options) {  
  2.   this.myVar = 1;  
  3.   this.someCallback = function (string) {  
  4.     console.log(string + '/' + this.myVar);  
  5.   }  
  6. }  
Az objektum saját magában további objektumot hoz létre, így:
  1. ...  
  2. this.server = new Server();  
  3. ...  
A Server objektum eseménykezelőjébe beillesztek egy bindet:
  1. ...  
  2. this.server.on('message'this.someCallback);  
  3. ...  
A gond ott van, hogy a this.someCallback scope-ja ezután nem a myObject lesz, hanem a Server, amiből nem tudom hogyan kellene kitörnöm (ugye a this.myVar a Server objektumban nincs benne, error).

A kérdés: milyen módszerrel szokás az ilyen helyzeteket megoldani? Van rá valami nyelvi eszköz?

#nodejs
 
1

proxy

Poetro · 2012. Dec. 30. (V), 02.27
Lehet használni proxy-t / bind-ot, ami módosítja a függvény scope-ját. Erre használható a Function beépített bind metódusa, illetve amennyiben az nem létezik, akkor vannak keretrendszerek, amit ezt lehetővé teszik. Ilyen például az Underscore.js bind metódusa, illetve a jQuery-s proxy függvény.

A fenti példát például a következő tökéletesen megoldja:
  1. this.server.on('message'this.someCallback.bind(this));   
2

De hogy értsd is amit Poetro

Karvaly84 · 2012. Dec. 30. (V), 02.44
De hogy értsd is amit Poetro mond: bind
3

[Megoldva]

deejayy · 2012. Dec. 30. (V), 11.44
Köszönöm mindkettőtöknek, pont ezt kerestem.
4

Vagy csinálhatod azt is,

RobbeR · 2012. Dec. 30. (V), 18.21
Vagy csinálhatod azt is, hogy:
  1. function myObject(options) {    
  2.   var that = this;  
  3.   this.myVar = 1;    
  4.   this.someCallback = function (string) {    
  5.     console.log(string + '/' + this.myVar);    
  6.   }    
  7. }   
És ha nem definiálsz "belsőbb" scope-ban that változót, akkor használhatod azt, mint a myObject referenciája.
5

Szerintem elírtad :)

MadBence · 2012. Dec. 30. (V), 23.00
Szerintem elírtad :)
6

1) Azért nem az az objektum

amcsi · 2013. Jan. 7. (H), 18.31
1) Azért nem az az objektum lesz a kontextus, amit szeretnél, mert csak maga a függvény objektumot adod át az .on metódusnak, amely egymaga nem tartalmazza, hogy milyen kontextusban van (ez teljesen természetes).
2) Azért a Server a kontextus, mert a Server objektumnak az .on metódusán belül szándékosan manipulálásra kerül a kontextus arra, hogy a Server legyen a kontextus; ezt a .call()/.apply() metódusokkal csinálta, amit minden böngészőben minden függvény objektumnak alap metódusai.

Az 1-es pontot nem tudod javítani, a 2-es pontot se (mivel ez a Server forráskódjában van), viszont te magad ki tudod trükközni, hogy a kellő kontextus legyen:
  1. function myObject(options) {    
  2.   this.myVar = 1;    
  3.   this.someCallback = function (string) {    
  4.     console.log(string + '/' + this.myVar);  
  5.     this.server = new Server();  
  6.     //this.server.on('message', this.someCallback);  
  7.     var me = this// "ezt" az objektumot hozzárendelheted egy új változóba, hogy itt definiált függvényeken belül el tudd érni ezt az objektumot (máskülönben a this egy másik függvényben már másra fog mutatni)  
  8.    this.server.on('message'function (arg1, arg2/*, ...argN*/) {  
  9.      me.someCallback(arg1, arg2/*, ...argN*/); // ez már a me-ből hívódik, amibe a korábbi this-t elmentettük, vagyis ez abból a kontextusból lesz hívva, amilyet szerettél volna.  
  10.      // ha nem tudni előre, mennyi argumentumot kell tovább passzolnod, a függvénynek .apply() segítségével lehet dinamikusan átadni argumentumokat  
  11.      /* 
  12.      me.someCallback.apply(me, //kontextus manipuláció, ami kötelező paraméter, amivel átírható a kontextus. A me a jó, úgyhogy beírjuk azt (kötelező, tehát be kell írni) 
  13.        arguments // argumentumok tovább passzolása. Elfogad nem-valódi tömböt is, mint az arguments, ha jól tudom. Különben, ha nincs igazam, akkor: Array.prototype.slice.call(arguments) 
  14.      ); 
  15.      */  
  16.    );  
  17.   }    
  18. }    
amit Poetro írt, az is ugyanezt csinálja jQuery-ben, de ezt tanítás céljából írtam neked, hogy kb. mit történik a jQuery .bind()-nál.