Что лежит в основе этой идиомы JavaScript: var self = this?

Я видел следующее в источнике WebKit HTML 5 SQL Storage Notes Demo:

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

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

Ответ 1

Смотрите эту статью на alistapart.com

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

Как объяснили другие, 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 и просто предположим, объем ограждающую.

Ответ 8

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

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

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

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

Ответ 9

Как уже упоминалось несколько раз, "я" просто используется для хранения ссылки на 'this' до входа в функцию. Как только функция 'this' ссылается на что-то еще.

Ответ 10

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