2011-11-08 10 views
7

Estoy desarrollando una extensión de Firefox y creo que ahora he llegado a un malentendido básico con respecto a Javascript, con el concepto de 'prototipo' para ser exacto. Consideremos el siguiente ejemplo mínima, notar las diferencias cuando me puse las variables this.demo y this.test:confundido con 'prototype' (extensión de 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 
); 

Al abrir Firefox me da la salida esperada:

Hello World 

Esto funciona siempre bien presente manera siempre que una llamada muestre() 'dentro' del archivo fuente js. Sin embargo, cuando llamo pantalla() a través correspondiente clic desde una entrada de menú, por ejemplo .:

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

me sale:

null World 

initialize() se ha llamado de antemano, por supuesto.

Todavía soy bastante nuevo en Javascript y trabajo con el código existente. Por lo tanto, estoy bastante confundido con el comportamiento actual. ¿Cuál es la mejor solución para obtener funciona?

+0

Salida estos dos artículos: http://www.javascriptkit.com/javatutors/oopjs2.shtml y http://mckoss.com/jscript/object.htm - su código es una especie de todo el lugar. Una cosa que ayudará mucho, creo, es no usar el nombre 'example' tanto para su definición como para su instancia; es más confuso cuando la mitad de su código está tratando con "ejemplo" esto y "ejemplo" que. Obtenga algunos términos reales allí: lo ayudará a pensar las cosas. –

+2

Si comprueba qué objeto es 'this' al llamar desde el elemento de menú, creo que encontrará que es el elemento de menú y no el objeto que esperaba. – some

+3

Por cierto, las matrices son para cuando las claves son enteros. En este caso use objetos: 'Example = {}'. (Además, incluso cuando necesite una matriz, debe usar '[]' en lugar de una nueva matriz. – hugomg

Respuesta

2

Porque this se está refiriendo al objeto que llama al método.

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! 

este ejemplo alertará "Foo Bar!" en lugar de "¡Hola mundo!"

de prevenir esta situación inesperada puede agregar un "punto de control" usando 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! 

Esto alertará "Hello World!" 'valor' de MyObject no el 'valor' de la etiqueta.

.

quizás esta otra situación que ayuda a entender

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

"Se trata de un pequeño perro"

0

Después de muchas más horas, he resuelto mi problema ... de alguna manera, no he entendido completamente hasta aquí.

En primer lugar, el ejemplo mínimo realmente funciona. Tengo el comportamiento extraño porque integré las líneas del código de ejemplo en el código de la aplicación. Sin embargo, "en el fondo" del código se produjo un error que chocó con la llamada de initialize(). Cuando pongo las líneas de código de ejemplo antes del código de la aplicación siempre obtengo la salida "Hello World" (en su lugar "null World" en un caso)

En segundo lugar, había un error fundamental en la aplicación. Es una extensión de Firefox con una barra lateral. Con eso window.addEventListener(...) se llama dos veces, una para la barra lateral, una para la ventana del navegador "normal". Por lo tanto, tenía dos window.obj separados. Y el código llama al initialize() solo para la barra lateral. En el 99% eso no fue un problema ya que la mayoría de los códigos usan la barra lateral window.obj. La llamada desde el menú contextual, sin embargo, se dirige al navegador window.obj. Como solución, cambié el código de tal manera que solo se usa la barra lateral window.obj.

Perdón por mirar en la dirección incorrecta. Muchas gracias por todas las respuestas. ¡Tus comentarios han vuelto al buen camino y definitivamente me han motivado! :)

Cristiano

Cuestiones relacionadas