Var self = this?

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

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

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

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

Ответы

Ответ 1

Этот вопрос не специфичен для 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 - это другая псевдо переменная, которую следует обрабатывать одинаково;— с помощью псевдонимов.

Ответ 3

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

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

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

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
  }
}

Ответ 4

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: несмотря на то, что вложенные функции внутри объекта берут объект глобального окна, а не окружающий объект.

Ответ 5

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

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

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

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

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

});

Ответ 9

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