var self = this? - PullRequest
       22

var self = this?

180 голосов
/ 03 декабря 2008

Использование методов экземпляра в качестве обратных вызовов для обработчиков событий изменяет область действия this с «Мой экземпляр» на «Независимо от того, что только что вызвано обратным вызовом» . Так что мой код выглядит так

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

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}

Это работает, но разве это лучший способ сделать это? Это выглядит странно для меня.

Ответы [ 8 ]

205 голосов
/ 03 декабря 2008

Этот вопрос относится не только к jQuery, но и к JavaScript в целом. Основная проблема заключается в том, как «направить» переменную во встроенные функции. Вот пример:

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!
  }
  ...
};

Этот метод основан на использовании замыкания. Но это не работает с this, потому что this является псевдопеременной, которая может динамически меняться от области действия к области видимости:

// 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!
  }
  ...
};

Что мы можем сделать? Присвойте его некоторой переменной и используйте через псевдоним:

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 не является уникальным в этом отношении: arguments является другой псевдопеременной, которая должна обрабатываться таким же образом & mdash; по псевдонимам.

17 голосов
/ 03 декабря 2008

Да, похоже, это общий стандарт. Некоторые кодеры используют себя, другие используют меня. Он используется в качестве ссылки назад на «реальный» объект, а не на событие.

Это то, что мне потребовалось немного времени, чтобы действительно получить, сначала это выглядит странно.

Обычно я делаю это прямо в верхней части моего объекта (извините за демо-код - он более концептуален, чем что-либо еще и не является уроком о превосходной технике кодирования):

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
  }
}
10 голосов
/ 13 сентября 2016

Если вы используете ES2015 или скрипт типа и ES5, то вы можете использовать функции стрелок в своем коде, и вы не столкнетесь с этой ошибкой, и это относится к желаемой области действия в вашем экземпляре.

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});
10 голосов
/ 26 апреля 2015
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: несмотря на то, что вложенные функции в объекте принимают объект глобального окна, а не окружающий объект.

4 голосов
/ 01 июня 2016

Одним из решений этой проблемы является привязка всего вашего обратного вызова к вашему объекту с помощью метода bind javascript.

Вы можете сделать это с помощью именованного метода,

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

doCallBack(MyNamedMethod.bind(this)); 

Или с анонимным обратным вызовом

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

Выполнение этих действий вместо обращения к var self = this показывает, что вы понимаете, как привязка this ведет себя в javascript и не зависит от ссылки на закрытие.

Кроме того, оператор жирной стрелки в ES6 в основном является тем же самым вызовом .bind(this) для анонимной функции:

doCallback( () => {
  // You can reference "this" here now
});
3 голосов
/ 03 декабря 2008

Я не использовал jQuery, но в такой библиотеке, как Prototype, вы можете привязать функции к определенной области видимости. Итак, с учетом этого ваш код будет выглядеть так:

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

Метод bind возвращает новую функцию, которая вызывает исходный метод с указанной вами областью действия.

1 голос
/ 30 октября 2015

Просто добавьте к этому, что в ES6 из-за функций стрелок вам не нужно это делать, поскольку они фиксируют значение this.

1 голос
/ 03 декабря 2008

Я думаю, что на самом деле это зависит от того, что вы собираетесь делать внутри вашей doSomething функции. Если вы собираетесь получить доступ к MyObject свойствам с помощью этого ключевого слова, то вы должны использовать это. Но я думаю, что следующий фрагмент кода также будет работать, если вы не делаете никаких специальных действий, используя object(MyObject) свойства.

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

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

});
...