ugrás a tartalomhoz

Ismételten this, de egy kis flash-el megkavarva.

therest · 2012. Feb. 24. (P), 21.54
Sziasztok!

Adott egy JS osztály, van egy metódusa. Ezt a metódust paraméterként adom egy flash objektumnak, amit swfobject-tel hozok létre, majd amikor szükséges flashből meghívom ExternalInterface.call-al. Ez működik is a lenti kóddal (bár abban koránt sem vagy biztos, hogy az adott példány metódusát hívja), azonban a this már a window-ra mutat amikor a függvény fut. A kérdés, valahogyan megoldható-e, hogy az ExternalInterface-ből hívott callback-eknél, hogy a this-en keresztül az eredeti objetumot érjem el? Persze különösebb hekkelések, eval, meg túl sok kód nélkül?

JS:ben

CJukebox=function() {
var v= {callback:this.onFinishedLoad};
var p= {};
var a = {id: "musicPlayer", name: "musicPlayer"};
swfobject.embedSWF("player.swf",placeholder", "10", "10", "8.0.35.0", "", v, p, a);
}
CJukebox.prototype.onFinshedLoad=function() {
console.log(this);
}

//valahol később:
new CJukebox();
Flashben:

ExternalInterface.call(callback);
 
1

függvény

Poetro · 2012. Feb. 24. (P), 22.11
Egy függvényt adsz át callback-nek. Ekkor hagyományos függvényként viselkedik. Egy függvény csak akkor viselkedik metódusként, ha akként van meghívva. Azaz
var jukebox = new CJukebox();
// Ekkor metódusként viselkedik, azaz a this a jukebox-ra mutat
jukebox.onFinishedLoad();

// Ekkor már az onfishload egy függvényre mutat, 
// nincs tudomása arról, hogy az valaminek valamikor a metódusa volt
var onfinishload = jukebox.onFinishedLoad;
onfinishload();

myObj = {
  callback: jukebox.onFinishedLoad
};
// Ekkor a this már a myObj-ra mutat, hiába mutatott korábban másra.
myObj.callback();
Ha mást szeretnél this-nek, akkor add meg azt explicit, vagy add át eleve az objektumot, aminek meg akarod hívni a metódusát, és hívd meg azt a metódusát az átadott objektumnak.
Vagy adj meg egy olyan callback-et aminek van arról tudomása, mi a this. További információkért ajánlom, hogy olvasd el a cikkemet a JavaScript függvényekről.
3

A javascripten belüli this

therest · 2012. Feb. 25. (Szo), 00.39
A javascripten belüli this már valamennyire tiszta a számomra, még ha nem is teljesen. A kérdés, hogy a flashen keresztül mennyire kivitelezhető az ilyesmi, hiszen egy teljesen más környezetbe kerül az adat, tehát a javascript objektumok értelmüket vesztik, szerintem (de aki jobban tudja elmondhatná).
Az ExternalInterface Call metódusa is csak egy String-et vár első paraméterként, ami a hívandó függvény neve.
Ami igazán problémás számomra: Szeretném az javascript objektum létrehozásakor beállítani a flash változókat, és nem szeretném átadni a callback nevét string formájában, mert azt kicsit hekknek érzem, vagy inkább úgy mondom kevésbé szépnek.

Tehát így megoldható a dolog, és a megfelelő objektumot kapom, csak csúnya:

var CJukebox=function() {
}
CJukebox.prototype.show(callback) {
var v= {callback:callback};  
var p= {};  
var a = {id: "musicPlayer", name: "musicPlayer"};  
swfobject.embedSWF("player.swf",placeholder", "10", "10", "8.0.35.0", "", v, p, a); 
}
CJukebox.prototype.onDone=function() {
console.log(this);
}
var jukebox=new CJukebox();
jukebox.show('jukebox.onDone'); //tudom a példány nevét, és átadom, szerintem csúnya
A kínom az, hogy szeretném még a konstruktorban letudni a flash initjét, ne kelljen külön függvény erre, és callback nevét is magától adja át a flash-nek a konstruktor, ne kelljen paraméterként átadni sehol.
Mivel nem tudjuk a konstruktorban a példány nevét (jukebox), ezért a fentiek az én elgondolásom szerint nem megoldhatóak, de talán itt valaki mond rá valami trükköt, vagy egyszerűen egy jobb megközelítést.
5

v

Poetro · 2012. Feb. 25. (Szo), 01.22
Én nem látok itt sehol függvény nevet átadva. Ahogy látom, egy objektum kerül átadásra az swfobject egyik metódusának. Ha pedig ez így van, akkor létrehozhatsz egy függvényt, ami tud arról, mi a jukebox objektumod, és annak hívja meg a megfelelő metódusát (mondjuk egy closure miatt).
2

Function.prototype.bind

Karvaly84 · 2012. Feb. 24. (P), 23.04
Function.prototype.bind
4

Uhh, nekem ez elég mély így

therest · 2012. Feb. 25. (Szo), 00.42
Uhh, nekem ez elég mély így első guglizásra, de holnap utána nézek. Esetleg kifejtenéd?
6

A lényeg, hogy a Function

Karvaly84 · 2012. Feb. 25. (Szo), 08.03
A lényeg, hogy a Function objektumok az ECMAScript 5-ben támogatják a bind metódust, amivel beállítható egy függvényen belül a this változó. Ha pl. MSIE vagy más szörnyedvények nem támogatnák akkor:

if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  
  
    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  
  
    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  
  
    return fBound;  
  };  
} 
forrás: bind
7

Poetro: A swfobject

therest · 2012. Feb. 25. (Szo), 12.35
Poetro:
A swfobject metodusának még objektumként(inkább tömbként kéne itt értelmezni nem?) adom át a leendő flash változókat: {callback:callback,msg:'Helló!'}, de ezek flashen belül már különálló változók amik ha jól láttam stringek (typeof ezt mondja). Tehát hogy az swfobject metódusa mit kap az mellékes szerintem, mert a flash saját környezetében minden string lesz.
Olyan objektumot ami ismeri adott jukebox-ot csak példányosítás után tudok csinálni, nekem pedig az fontos, hogy egy jukebox létrehozása egy soros legyen csak paraméterezni kelljen. De azért az eddigiek mentén elgondolkodva lett egy ötletem, és írtam valamit (lásd lentebb).

Karway:
Ez elég érdekes dolog, valami amit nem ismertem eddig és hasznos. De ha jól látom itt is konstruktoron kívül kell megcsinálni dolgokat, ami nem jó, és az esetleges kompatibilitási kérdéseknek is utána kell olvasni még.


Végül a következő megoldással álltam elő:

var CJukebox=funtion(callback) {  
var v= {callback:callback};    
var p= {};    
var a = {id: "musicPlayer", name: "musicPlayer"};    
swfobject.embedSWF("player.swf",placeholder", "10", "10", "8.0.35.0", "", v, p, a);   
}  
CJukebox.prototype.onDone=function() {  
console.log(this);  
}  
var CJukeboxControl=function(){};
CJukeboxControl.prototype.newJukebox(name) {
window[name]=new CJukebox(name+'.onDone');
}
jukeBoxControl=new CJukeboxControl();
jukeBoxControl.newJukebox('first'); // ez az egysoros létrehozás
A fentiekkel megvan a golbális first nevű objektumom, a példányosítás egysoros, és a this is megfelelő, az onDone függvényben.

Mit gondoltok?