var self = this?

Używanie metod instancji jako wywołań zwrotnych dla programów obsługi zdarzeń zmienia zakres this z "Moja instancja" na "cokolwiek właśnie wywołało wywołanie zwrotne". Więc mój kod wygląda tak

function MyObject() {
  this.doSomething = function() {
    ...
  }

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}
To działa, ale czy to najlepszy sposób? Dla mnie to wygląda dziwnie.
Author: Steve Konves, 2008-12-03

8 answers

To pytanie nie jest specyficzne dla jQuery, ale specyficzne dla JavaScript w ogóle. Podstawowym problemem jest sposób "kanałowania" zmiennej w funkcjach wbudowanych. To jest przykład:

var abc = 1; // we want to use this variable in embedded functions

function xyz(){
  console.log(abc); // it is available here!
  function qwe(){
    console.log(abc); // it is available here too!
  }
  ...
};
[[7]}ta technika polega na użyciu zamknięcia. Ale to nie działa z this Ponieważ this jest pseudo zmienną, która może zmieniać się dynamicznie z zakresu na zakres:
// we want to use "this" variable in embedded functions

function xyz(){
  // "this" is different here!
  console.log(this); // not what we wanted!
  function qwe(){
    // "this" is different here too!
    console.log(this); // not what we wanted!
  }
  ...
};
Co możemy zrobić? Przypisanie go do jakiejś zmiennej i użycie go za pomocą aliasu:
var abc = this; // we want to use this variable in embedded functions

function xyz(){
  // "this" is different here! --- but we don't care!
  console.log(abc); // now it is the right object!
  function qwe(){
    // "this" is different here too! --- but we don't care!
    console.log(abc); // it is the right object here too!
  }
  ...
};

this nie jest unikalny w tym respect: {[6] } jest drugą pseudo zmienną, która powinna być traktowana w ten sam sposób-przez aliasing.

 200
Author: Eugene Lazutkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-21 19:32:24

Tak, to wydaje się być powszechnym standardem. Niektórzy programiści używają siebie, inni mnie. Jest używany jako odniesienie do "prawdziwego" obiektu w przeciwieństwie do zdarzenia.

To coś, co zajęło mi trochę czasu, aby naprawdę dostać, to wygląda dziwnie na początku.

Zwykle robię to na samej górze mojego obiektu (wybacz mój kod demo - jest bardziej koncepcyjny niż cokolwiek innego i nie jest lekcją doskonałej techniki kodowania): {]}

function MyObject(){
  var me = this;

  //Events
  Click = onClick; //Allows user to override onClick event with their own

  //Event Handlers
  onClick = function(args){
    me.MyProperty = args; //Reference me, referencing this refers to onClick
    ...
    //Do other stuff
  }
}
 16
Author: BenAlabaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-03 17:11:05
var functionX = function() {
  var self = this;
  var functionY = function(y) {
    // If we call "this" in here, we get a reference to functionY,
    // but if we call "self" (defined earlier), we get a reference to function X.
  }
}

Edit: pomimo tego, zagnieżdżone funkcje w obiekcie przejmują obiekt global window, a nie obiekt otaczający.

 8
Author: serkan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-01 10:16:27

Jeśli robisz ES2015 lub robisz type script i ES5, możesz użyć funkcji strzałek w kodzie i nie napotkasz tego błędu i odnosi się to do żądanego zakresu w Twojej instancji.

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});
 8
Author: Aran Dekar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 22:39:31

Nie używałem jQuery, ale w bibliotece takiej jak Prototype można powiązać funkcje do określonego zakresu. Więc mając to na uwadze Twój kod wyglądałby tak:

 $('#foobar').ready('click', this.doSomething.bind(this));

Metoda bind zwraca nową funkcję, która wywołuje oryginalną metodę z określonym zakresem.

 3
Author: neonski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-03 17:16:16

Jednym z rozwiązań jest powiązanie wszystkich połączeń zwrotnych z obiektem za pomocą metody bind javascript.

Możesz to zrobić za pomocą metody nazwanej,

function MyNamedMethod() {
  // You can now call methods on "this" here 
}

doCallBack(MyNamedMethod.bind(this)); 

Lub z anonimowym wywołaniem zwrotnym

doCallBack(function () {
  // You can now call methods on "this" here
}.bind(this));

Robienie tego zamiast uciekania się do var self = this pokazuje, jak powiązanie this zachowuje się w javascript i nie polega na odwołaniu do zamknięcia.

Operator strzałki fat w ES6 zasadniczo jest tym samym wywołaniem .bind(this) w funkcji anonimowej:

doCallback( () => {
  // You can reference "this" here now
});
 3
Author: bartdorsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-01 18:55:50

Myślę, że to zależy od tego, co zamierzasz zrobić wewnątrz swojej funkcji doSomething. Jeśli chcesz uzyskać dostęp do właściwości MyObject używając tego słowa kluczowego, musisz go użyć. Ale myślę, że poniższy fragment kodu będzie również działał, jeśli nie robisz żadnych specjalnych rzeczy używając właściwości object(MyObject).

function doSomething(){
  .........
}

$("#foobar").ready('click', function(){

});
 1
Author: Scott Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-11 13:18:26

Dodam tylko, że w ES6 ze względu na funkcje strzałek nie powinieneś tego robić, ponieważ przechwytują one wartość this.

 1
Author: aug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 21:56:31