2011-11-08 11 views
7

Pracuję nad rozszerzeniem firefox i myślę, że mam teraz podstawowe nieporozumienie dotyczące Javascriptu, z koncepcją "prototypu", aby być dokładnym. Rozważmy następujący minimalny przykład, zauważyć różnice kiedy ustawić zmienne this.demo i this.test:mylić z "prototypem" (rozszerzenie Firefoksa)

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 
); 

Podczas otwierania Firefoksa uzyskać oczekiwany wynik:

Hello World 

To działa zawsze dobrze to sposób tak długo, jak wyświetlanie połączenia() "wewnątrz" pliku źródłowego js. Jednak, gdy zgłoszę display() poprzez kliknięcie odpowiedniego wpisu z menu, np .:

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

uzyskać:

null World 

initialize() została wywołana wcześniej, oczywiście.

Nadal jestem całkiem nowy w JavaScript i pracuję z istniejącym kodem. Dlatego jestem bardzo zdezorientowany obecnym zachowaniem. Jakie są najlepsze rozwiązania do uzyskania?

+0

Sprawdź te dwa artykuły: http://www.javascriptkit.com/javatutors/oopjs2.shtml i http://mckoss.com/jscript/object.htm - kod jest rodzaj z całego miejsca. Jedną rzeczą, która może bardzo pomóc, to nie używać nazwy 'przykład' zarówno dla twojej definicji, jak i instancji; jest to bardziej mylące, gdy połowa kodu ma do czynienia z "przykładem" to i "przykładem", że. Zdobądź tam prawdziwe terminy - pomoże ci to przemyśleć. –

+2

Jeśli sprawdzisz, jaki przedmiot jest "ten" podczas wywoływania z menuitem, myślę, że zobaczysz, że jest to menuitem, a nie obiekt, którego się spodziewałeś. – some

+3

btw, Tablice są dla kiedy klucze są liczbami całkowitymi. W takim przypadku użyj obiektów: 'Example = {}'. (Również, gdy potrzebujesz tablicy, powinieneś użyć '[]' zamiast nowej tablicy. – hugomg

Odpowiedz

2

Ponieważ this odwołuje się do obiektu, który wywołuje metodę.

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! 

ten przykład wyświetli komunikat "Foo Bar!" zamiast "Hello World!"

aby temu zapobiec nieoczekiwanych sytuacjach można dodać "Checkpoint" za pomocą 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! 

to będzie ostrzegać "Hello World!" "wartość" z MyObject nie "wartość" tagu.

.

może to inna sytuacja pomaga Ci zrozumieć

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

„To jest mały pies”

0

Po wielu więcej godzin, mogę rozwiązać mój problem ... jakoś, nie w pełni zrozumiałe jak dotąd.

Po pierwsze, minimalny przykład faktycznie działa. Mam dziwne zachowanie, ponieważ zintegrowałem linie przykładowego kodu z kodem aplikacji. Jednak "głęboko" w kodzie wystąpił błąd, który zderzył się z wywołaniem funkcji initialize(). Kiedy wstawiam przykładowe linie kodu przed kodem aplikacji, zawsze otrzymuję wyjście "Hello World" (zamiast tego "null World" w jednym przypadku)

Po drugie, w aplikacji wystąpił zasadniczy błąd. Jest to rozszerzenie Firefoksa z bocznym paskiem. Dzięki temu window.addEventListener(...) jest wywoływana dwa razy, raz dla paska bocznego, raz dla "normalnego" okna przeglądarki. Dlatego miałem dwa oddzielne window.obj. A kod wywołuje initialize() tylko dla tego paska bocznego. W 99% nie było to problemem, ponieważ większość kodu używa paska bocznego window.obj. Jednak wywołanie z menu kontekstowego jest kierowane na przeglądarkę window.obj. Jako rozwiązanie zmieniłem kod w taki sposób, że używany jest tylko pasek boczny window.obj.

Przepraszamy za patrzenie w niewłaściwym kierunku. Bardzo dziękuję za wszystkie odpowiedzi. Twoje komentarze powróciły na właściwą drogę i zdecydowanie podtrzymały motywację! :)

Christian

Powiązane problemy