2010-02-12 16 views
7

Mam klasy JavaScript, który wygląda tak:Zakres „to” w JavaScript

function SomeFunction() 
{ 
    this.doSomething(function() 
    { 
     this.doSomethingElse(); 
    }); 

    this.doSomethingElse = function() 
    { 

    } 
} 

Ten kod wygeneruje błąd, ponieważ zakres „to” wewnątrz funkcji, która jest przekazywana do doSomething() jest inny niż zakres "tego" poza tą funkcją.

Rozumiem, dlaczego tak jest, ale jaki jest najlepszy sposób, aby sobie z tym poradzić? Właśnie to robię:

function SomeFunction() 
{ 
    var thisObject = this; 

    this.doSomething(function() 
    { 
     thisObject.doSomethingElse(); 
    }); 

    this.doSomethingElse = function() 
    { 

    } 
} 

To działa dobrze, ale po prostu wydaje się być hakiem. Zastanawiam się, czy ktoś ma lepszy sposób.

+2

@Jon Kruger To też robię. Myślę, że to całkiem normalne. Możesz zmienić 'this' za pomocą' call' i 'apply', ale to nie zawsze pasuje do tego, co robisz dobrze. Inną opcją jest podanie 'this' jako parametru, ale to wydaje się być jeszcze bardziej hackerem. –

+0

@ Jonaton Co masz na myśli przez "Możesz to zmienić za pomocą połączenia i aplikacji"? –

+1

@Jon Kruger Zobacz także: "call": https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Function/Apply –

Odpowiedz

10

Jest to poprawne i powszechnie akceptowane obejście. To trochę kludgy, ale to jest to, co każdy robi. Zazwyczaj ta dodatkowa zmienna nazywa self, jak w:

function SomeFunction() 
{ 
    var self = this; 

    this.doSomething(function() 
    { 
     self.doSomethingElse(); 
    }); 

    this.doSomethingElse = function() 
    { 

    } 
} 
+1

Należy pamiętać, że 'self' jest właściwością obiektu window w przeglądarkach, które wskazuje na siebie, chociaż jest mało prawdopodobne, aby powodowało jakiekolwiek problemy. –

+0

Innymi nazwami, które widziałem, używane są w dużym stopniu 'to' i' me', w zależności od kontekstu. – cHao

3

this ma dynamiczny "zakres". Oznacza to, że jest on konfigurowany przez to, co wiąże, i jest związany "wywołaniem metody". Oznacza to, że każdyczas w programie widać to: w.f() następnie podczas f jest wykonywany, this dynamicznie związana f, nawet jeśli f miał this swoim zakresem leksykalnym.

Większość frameworków JavaScript zapewnia pewne możliwości rozwiązania tego problemu. Z Prototype.js (na przykład) można to zrobić:

this.doSomething(function() { this.doSomethingElse(); }.bind(this)); 

Twój "hack" jednak jest w porządku. Zwykle robię (function (self) { ... })(this) wokół dowolnych funkcji, których potrzebuję leksykalną zmienną o rozmiarach this.

1

Warto również wspomnieć, że następna wersja ECMAScript (specyfikacja językowa dla JavaScript) wprowadzi Function.bind(), która pozwoli ci określić stały kontekst dla funkcji.