ugrás a tartalomhoz

OOP Callback, this?

deejayy · 2012. Dec. 30. (V), 01.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:

function myObject(options) {
  this.myVar = 1;
  this.someCallback = function (string) {
    console.log(string + '/' + this.myVar);
  }
}
Az objektum saját magában további objektumot hoz létre, így:

  ...
  this.server = new Server();
  ...
A Server objektum eseménykezelőjébe beillesztek egy bindet:

  ...
  this.server.on('message', this.someCallback);
  ...
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), 01.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:
this.server.on('message', this.someCallback.bind(this)); 
2

De hogy értsd is amit Poetro

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

[Megoldva]

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

Vagy csinálhatod azt is,

RobbeR · 2012. Dec. 30. (V), 17.21
Vagy csinálhatod azt is, hogy:
function myObject(options) {  
  var that = this;
  this.myVar = 1;  
  this.someCallback = function (string) {  
    console.log(string + '/' + this.myVar);  
  }  
} 
É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), 22.00
Szerintem elírtad :)
6

1) Azért nem az az objektum

amcsi · 2013. Jan. 7. (H), 17.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:
function myObject(options) {  
  this.myVar = 1;  
  this.someCallback = function (string) {  
    console.log(string + '/' + this.myVar);
    this.server = new Server();
    //this.server.on('message', this.someCallback);
    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)
   this.server.on('message', function (arg1, arg2/*, ...argN*/) {
     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.
     // ha nem tudni előre, mennyi argumentumot kell tovább passzolnod, a függvénynek .apply() segítségével lehet dinamikusan átadni argumentumokat
     /*
     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)
       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)
     );
     */
   );
  }  
}  
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.