2012-05-30 11 views
7

Widziałem to zrobić dużo w JavaScript i pamiętam, aby dowiedzieć się, dlaczego, ale nie pamiętam odpowiedzi.Dlaczego warto utworzyć zmienną o wartości to

Zgaduję, że to ma coś wspólnego z zakresem i funkcji nazywany poza „klasą”, ale dlaczego należałoby to zrobić (najlepiej przedstawiający przykładowe):

function myClass() 
{ 
    var self = this; 

    //... 

    this.myArray = []; 

    this.myFunc = function() { alert(self.myArray.length); }; 
} 

Odpowiedz

5

W celu zatrzask na zmienna jako część closure.

Na przykład:

MyClass.prototype.doStuff = function(){ 
    this.foundItems = []; 
    var self = this; 
    this.myString.replace(/.../,function(){ 
    // `this` is actually the `window` inside this callback 
    // so we need to use `self` to invoke another method on our instance object 
    self.foundItems.push(self.doOtherStuff()); 
    }); 
}; 

Konkretny przykład napisałeś nie wymaga zamknięcia jeśli wywołać metodę w oczekiwanym sposób:

function Foo(){ 
    this.array = []; 
    this.myFunc = function(){ 
    return this.array; 
    } 
} 
var foo = new Foo; 
foo.myFunc(); // [] 

Jednakże, jest to możliwe, aby „złamać” go tak:

var f2 = foo.myFunc; 
f2(); // undefined, since `this` was the window 

Twój kod za pomocą zamknięcia jest bezpieczny przed tego rodzaju t omufowanie.

+0

więc moim przykładzie (zaktualizowany), chciałbym nadal potrzebują 'self' przed uzyskaniem dostępu do' myArray 'w funkcji' myFunc'? – Cheetah

+0

Ten konkretny przykład nie jest zbyt dobry, "forEach" przyjmuje drugi argument, który będzie związany z 'tym' wewnątrz wywołania zwrotnego, co powinno być preferowane w stosunku do tworzenia "hacky" zmiennej 'self'. – Esailija

+0

@Ben To zależy od sposobu wywołania metody. Na przykład: 'var o = {f: function() {return this}}; o.f() == o;/* true */var f2 = o.f; f2() == okno;/* true */' – Phrogz

2

"ten" odnosi się do bieżącego "obiektu". Moc dotyczy, gdy mówimy o javascript, na fakt, że "to" wyrażenie jest oceniane w kontekście, więc na przykład, jeśli metoda jest wykonywana w innym kontekście obiektu, "ta" wartość zmieni się odpowiednio.

1

Jeśli utworzysz funkcję w ramach innej funkcji, dla funkcji wewnętrznej zostanie ustawiony globalny obiekt okna. Jeśli utworzyć zmienną zbawczą wartość this, jak

var that = this; 

następnie można użyć that odwołać funkcję zewnętrzną w funkcji wewnętrznej.

0

Oprócz niektórych odpowiedzi opublikowanych przez innych użytkowników, ustawienie zmiennej do tego umożliwia ponowne użycie zmiennych bez uzyskiwania dostępu do obiektów.

Podobnie robi coś takiego:

var myElement = document.getElementById('someElement'); 

I wtedy dostępu myelement jeśli trzeba raczej niż document.getElementById wiele razy.

Ustawienie, że = to lub self = to daje dostęp wszędzie do "tego" lub "siebie" i zapobiega ponownemu ładowaniu jakiegoś obiektu.

0

nie sądzę naprawdę chce to zrobić:

  • Wszelkie czas instancja jest tworzona, można również stworzyć „kopiuj” funkcji. A więc 5 wystąpień, utworzy 5 "kopii" funkcji.
  • Ta "kopia" funkcji jest powiązana z otoczeniem, które jest istotne tylko dla tej konkretnej instancji, więc nie może być używana w sposób ogólny. Oznacza to, że klasa rozszerzająca otrzyma metodę, która ma znaczenie tylko w przypadku niektórych instancji klasy nadrzędnej, która prawdopodobnie nie jest nawet używana.
  • Twoje wcięcie będzie wymknąć się spod kontroli, zwłaszcza jeśli zaczynają gniazdowania tych funkcji wbudowanych
  • Musisz polować na funkcji wewnątrz innych funkcji, a nie tylko szuka go w definicji prototypu

alternatywnej :

function MyClass() { 
    this.myArray = []; 
    this.myFunc = this.myFunc.bind(this); //The "blueprint" in the prototype is not affected, the instance gets its own bound version. 
              //This means the one in prototype can be inherited or used generically anywhere else as well 
} 

MyClass.prototype = { 

    myFunc: function() { //My func is neatly listed in the prototype and can use `this` normally 
     alert(this.myArray.length); 
    }, 

    constructor: MyClass 
}; 


var myObj = new MyClass(); 

document.addEventListener("click", myObj.myFunc); //Will now work as you "expect" it to work 

kilka wad:

  • Każda funkcja związana to nowa funkcja, więc na przykład 1 nowa funkcja jest wciąż tworzona za każdym razem.
  • Gotowa na piśmie wszystkie połączenia .bind w konstruktorze, ale można złagodzić za pomocą pomocnika jak _.bindAll
Powiązane problemy