2011-11-08 17 views
7

Sto sviluppando un'estensione per Firefox e penso di aver subito un malinteso di base per quanto riguarda Javascript, con il concetto di "prototipo" per essere precisi. Si consideri il seguente esempio minimo, notare le differenze quando ho impostato le variabili this.demo e this.test:confuso con "prototype" (estensione per Firefox)

var Example = new Array(); 

    Example.Foo = function() { 
    this.test = null; 
    this.demo = "World"; 
    }; 

    Example.Foo.prototype = { 

    initialize : function(resource) { 
     this.test = "Hello"; 
     this.display(); 
    }, 

    display : function() { 
     alert(this.test + " " + this.demo); 
    }, 
    } 

    window.addEventListener(
    "load", 
    function() { 
     window.obj = new Example.Foo(); 
     obj.initialize(); 
    }, 
    false 
); 

Nell'aprire Firefox ottengo i risultati attesi:

Hello World 

questo funziona sempre bene questo modo fino a quando una chiamata display() 'all'interno' il file di origine js. Tuttavia, quando chiamo display() tramite corrispondente click da una voce di menu, ad es .:

... 
    <menupopup id="menu_ToolsPopup"> 
     <menuitem label="Example" oncommand="obj.display();"/> 
    </menupopup> 
... 

ottengo:

null World 

initialize() è stato chiamato in anticipo, naturalmente.

Sono ancora piuttosto nuovo su Javascript e lavoro con codice esistente. Sono quindi abbastanza confuso con il comportamento attuale. Qual è la migliore soluzione per ottenere funziona?

+0

Guarda anche questi due articoli: http://www.javascriptkit.com/javatutors/oopjs2.shtml e http://mckoss.com/jscript/object.htm - il codice è tipo di tutto il posto. Una cosa che aiuterà molto, penso, è non usare il nome 'example' per la tua definizione e istanza; è più confuso quando metà del tuo codice ha a che fare con "esempio" questo e "esempio" quello. Ottieni alcuni termini reali - ti aiuterà a riflettere. –

+2

Se si controlla quale oggetto 'questo? È quando si chiama dal menuitem, penso che scoprirete che è il menu e non l'oggetto che vi aspettavate. – some

+3

btw, le matrici sono per quando le chiavi sono numeri interi. In questo caso usa gli oggetti: 'Esempio = {}'. (Inoltre, anche quando hai bisogno di un array dovresti usare '[]' invece della nuova matrice. – hugomg

risposta

2

Perché this fa riferimento all'oggetto che chiama il metodo.

var MyObject= new function(){ 

    this.value="Hello World!"; 

    this.display=function(){ 
     alert(this.value); 
    } 
} 

<input type="button" value="Foo Bar!" onclick="MyObject.display()"> //Foo Bar! 

questo esempio avviserà "Foo Bar!" invece di "Hello World!"

per impedire questo situazioni inaspettate è possibile aggiungere un "punto di controllo" utilizzando var that=this;

var MyObject= new function(){ 

    var that=this; // <--- reference to actual object 

    this.value="Hello World"; 

    this.display=function(){ 
     alert(that.value); 
    } 

} 

<input type="button" value="Foo Bar!" onclick="MyObject.display()"> //Hello World! 

questo avviserà "Ciao Mondo!" 'valore' da MyObject non il 'valore' del tag.

.

forse quest'altra situazione aiuterà a capire

<img scr="dog.gif" title="Little Dog" onclick="alert('This is a '+this.title)"> 

"Si tratta di un piccolo cane"

0

Dopo molte ore, ho risolto il mio problema ... in qualche modo, non ho pienamente compreso finora.

In primo luogo, l'esempio minimo funziona effettivamente. Ho uno strano comportamento perché ho integrato le righe del codice di esempio nel codice dell'applicazione. Tuttavia, "in profondità" nel codice si è verificato un errore che si è scontrato con la chiamata di initialize(). Quando inserisco le righe di codice di esempio prima del codice dell'applicazione ottengo sempre l'output "Hello World" (invece "null World" in un caso)

In secondo luogo, c'era un difetto fondamentale nell'applicazione. È un'estensione per Firefox con una barra laterale. Con questo window.addEventListener(...) viene chiamato due volte, una volta per la barra laterale, una volta per la finestra del browser "normale". Ho quindi avuto due separati window.obj. E il codice chiama initialize() solo per la barra laterale. Nel 99% non è stato un problema poiché la maggior parte del codice utilizza la barra laterale window.obj. La chiamata dal menu di scelta rapida, tuttavia, ha come target il browser window.obj. Come soluzione ho cambiato il codice in modo tale da utilizzare solo la barra laterale window.obj.

Ci scusiamo per aver guardato nella direzione sbagliata. Grazie mille per tutte le risposte. I tuoi commenti sono tornati sulla strada giusta e mi hanno sicuramente motivato! :)

Christian

Problemi correlati