Что лежит в основе этой идиомы JavaScript: var self = this? - PullRequest
346 голосов
/ 07 июня 2009

В исходном тексте для WebKit HTML 5 заметки о хранилище SQL замечено следующее: :

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

Автор использует self в некоторых местах (тело функции) и this в других местах (тела функций, определенных в списке аргументов методов). В чем дело? Теперь, когда я заметил это однажды, я начну видеть это везде?

Ответы [ 10 ]

419 голосов
/ 07 июня 2009

См. статью на alistapart.com

self используется для сохранения ссылки на оригинал this даже при изменении контекста. Эта техника часто используется в обработчиках событий (особенно в замыканиях).

96 голосов
/ 24 сентября 2013

Я думаю, что имя переменной 'self' больше не следует использовать таким образом, поскольку современные браузеры предоставляют глобальную переменную self, указывающую на глобальный объект либо обычного окна, либо WebWorker.

Чтобы избежать путаницы и потенциальных конфликтов, вы можете написать var thiz = this или var that = this.

34 голосов
/ 07 июня 2009

Да, вы увидите это повсюду. Это часто that = this;.

Посмотрите, как self используется внутри функций, вызываемых событиями? У них будет свой контекст, поэтому self используется для хранения this, который вошел в Note().

Причина, по которой self все еще доступна для функций, даже если они могут выполняться только после завершения функции Note(), заключается в том, что внутренние функции получают контекст внешней функции из-за закрытие .

28 голосов
/ 22 ноября 2011

Следует также отметить, что существует альтернативный шаблон Proxy для сохранения ссылки на исходный this в обратном вызове, если вам не нравится идиома var self = this.

Поскольку функцию можно вызывать с заданным контекстом, используя function.apply или function.call, вы можете написать оболочку, которая возвращает функцию, которая вызывает вашу функцию с apply или call, используя данный контекст. См. Функцию jQuery proxy для реализации этого шаблона. Вот пример его использования:

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFunc может быть вызван и будет иметь вашу версию this в качестве контекста.

9 голосов
/ 16 марта 2015

Это причуда JavaScript. Когда функция является свойством объекта, более метко названным методом, это относится к объекту. В примере обработчика события содержащий объект является элементом, который вызвал событие. Когда вызывается стандартная функция, это будет ссылаться на глобальный объект. Если у вас есть вложенные функции, как в вашем примере, это вообще не относится к контексту внешней функции. Внутренние функции совместно используют область действия с содержащейся функцией, поэтому разработчики будут использовать варианты var that = this, чтобы сохранить this , который им нужен во внутренней функции.

9 голосов
/ 07 июня 2009

Переменная фиксируется встроенными функциями, определенными в методе. this в функции будет ссылаться на другой объект. Таким образом, вы можете заставить функцию содержать ссылку на this во внешней области видимости.

8 голосов
/ 30 января 2018

Как объяснили другие, var self = this; позволяет коду в замыкании ссылаться на родительскую область.

Однако сейчас 2018 год, и ES6 широко поддерживается всеми основными веб-браузерами. Идиома var self = this; не так важна, как раньше.

Теперь можно избежать var self = this; с помощью функций стрелок .

В тех случаях, когда мы использовали бы var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

Теперь мы можем использовать функцию стрелки без var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

Функции стрелок не имеют своих собственных this и просто предполагают объем, в котором они заключены.

5 голосов
/ 22 мая 2014

На самом деле self - это ссылка на окно (window.self), поэтому, когда вы говорите var self = 'something', вы переопределяете ссылку на себя, потому что self существует в объекте окна.

Именно поэтому большинство разработчиков предпочитают var that = this над var self = this;

Во всяком случае; var that = this; не соответствует хорошей практике ... при условии, что другие разработчики будут позже пересматривать / изменять ваш код, вам следует использовать самые распространенные стандарты программирования в отношении сообщества разработчиков

Поэтому вы должны использовать что-то вроде var oldThis / var oThis / etc - чтобы быть понятным в вашей области видимости // .. это не так уж много, но сэкономит несколько секунд и несколько циклов работы мозга

0 голосов
/ 02 августа 2018
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call (thatt);

0 голосов
/ 27 декабря 2014

Как уже упоминалось несколько раз выше, «я» просто используется, чтобы сохранить ссылку на «это» до входа в функцию. Однажды в функции «это» относится к чему-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...