У меня есть функция конструктора, которая регистрирует обработчик событий:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
Однако я не могу получить доступ к data
свойству созданного объекта внутри обратного вызова. Похоже this
, не относится к объекту, который был создан, но относится к другому.
Я также попытался использовать объектный метод вместо анонимной функции:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
но это показывает те же проблемы.
Как я могу получить доступ к нужному объекту?
javascript
callback
this
Феликс Клинг
источник
источник
Ответы:
Что вы должны знать о
this
this
(он же «контекст») - это специальное ключевое слово внутри каждой функции, и его значение зависит только от того, как была вызвана функция, а не от того, как / когда / где она была определена. На него не влияют лексические области, как и другие переменные (кроме функций со стрелками, см. Ниже). Вот некоторые примеры:Чтобы узнать больше
this
, взгляните на документацию MDN .Как правильно сослаться на
this
Не использовать
this
Вы на самом деле не хотите получать доступ,
this
в частности, к объекту, на который он ссылается . Вот почему простое решение - просто создать новую переменную, которая также ссылается на этот объект. Переменная может иметь любое имя, но наиболее распространенными являютсяself
иthat
.Поскольку
self
это обычная переменная, она подчиняется лексическим правилам области видимости и доступна внутри обратного вызова. Это также имеет то преимущество, что вы можете получить доступ кthis
значению самого обратного вызова.Явный набор
this
обратного вызова - часть 1Может показаться, что вы не контролируете значение,
this
потому что его значение устанавливается автоматически, но на самом деле это не так.Каждая функция имеет метод
.bind
[docs] , который возвращает новую функцию сthis
привязкой к значению. Функция действует точно так же, как и та, которую вы вызывали.bind
, только то, чтоthis
было установлено вами. Независимо от того, как или когда эта функция вызывается,this
всегда будет ссылаться на переданное значение.В этом случае, мы являемся обязательными для выполнения обратного вызова - х
this
к значениюMyConstructor
х ггthis
.Примечание. При связывании контекста для jQuery используйте вместо него
jQuery.proxy
[docs] . Причина этого заключается в том, что вам не нужно сохранять ссылку на функцию при отмене привязки обратного вызова события. JQuery обрабатывает это внутренне.ECMAScript 6: использовать функции стрелок
ECMAScript 6 представляет функции стрелок , которые можно рассматривать как лямбда-функции. У них нет собственной
this
привязки. Вместо этогоthis
ищется в области видимости, как обычная переменная. Это означает, что вам не нужно звонить.bind
. Это не единственное специальное поведение, которое они имеют, пожалуйста, обратитесь к документации MDN для получения дополнительной информации.Набор
this
обзвона - часть 2Некоторые функции / методы, которые принимают обратные вызовы, также принимают значение, на которое
this
должен ссылаться обратный вызов . По сути, это то же самое, что связывать его самостоятельно, но функция / метод делает это за вас.Array#map
[Документы] такой метод. Его подпись:Первый аргумент - это обратный вызов, а второй аргумент - это значение, на которое
this
должно ссылаться. Вот надуманный пример:Примечание. Вопрос о том, можете ли вы передать значение,
this
обычно упоминается в документации к этой функции / методу. Например, метод jQuery [docs]$.ajax
описывает параметр под названиемcontext
:Распространенная проблема: использование объектных методов в качестве обратных вызовов / обработчиков событий
Другое распространенное проявление этой проблемы - когда объектный метод используется в качестве обработчика обратного вызова / события. Функции являются первоклассными гражданами в JavaScript, а термин «метод» - это просто разговорный термин для функции, которая является значением свойства объекта. Но эта функция не имеет конкретной ссылки на свой «содержащий» объект.
Рассмотрим следующий пример:
Функция
this.method
назначается в качестве обработчика события щелчка, но еслиdocument.body
щелкнуть, зарегистрированное значение будетundefined
, поскольку внутри обработчика событияthis
ссылается наdocument.body
, а не на экземплярFoo
.Как уже упоминалось в начале, то , что
this
относится к зависит от того, как функция называется , не так, как она определена .Если бы код был похож на следующий, может быть более очевидно, что функция не имеет неявной ссылки на объект:
Решение такое же, как упомянуто выше: если доступно, используйте
.bind
для явного связыванияthis
с конкретным значениемили явно вызвать функцию как «метод» объекта, используя анонимную функцию в качестве обработчика обратного вызова / события, и назначить объект (
this
) другой переменной:или используйте функцию стрелки:
источник
self
иthat
ссылаться наthis
. Я чувствую это так, потомуthis
что перегруженная переменная используется в разных контекстах; тогда какself
обычно соответствует локальному экземпляру иthat
обычно относится к другому объекту. Я знаю, что вы не установили это правило, как я видел, как оно появилось в ряде других мест, но это также то, почему я начал использовать_this
, но не уверен, что чувствуют другие, за исключением неоднородной практики что привело.Function.prototype.call ()
и наFunction.prototype.apply ()
. Особенно сapply ()
я получил много пробега. Я менее склонен использовать,bind ()
возможно, только по привычке, хотя я знаю (но не уверен), что могут быть небольшие накладные преимущества при использовании привязки по сравнению с другими вариантами.() => this.clicked()
;)Вот несколько способов получить доступ к родительскому контексту внутри дочернего контекста:
bind()
функцию.1. Используйте
bind()
функциюЕсли вы используете
underscore.js
- http://underscorejs.org/#bind2 Сохраните ссылку на context / this внутри другой переменной
3 Стрелка
источник
Это все в "волшебном" синтаксисе вызова метода:
Когда вы получаете свойство от объекта и вызываете его за один раз, объект будет контекстом для метода. Если вы вызываете тот же метод, но в отдельных шагах, вместо этого контекст является глобальной областью (окном):
Когда вы получаете ссылку на метод, он больше не привязывается к объекту, это просто ссылка на простую функцию. То же самое происходит, когда вы получаете ссылку для использования в качестве обратного вызова:
Вот где вы бы связали контекст с функцией:
Если вы используете jQuery, вы должны использовать
$.proxy
вместо этого метод, так какbind
он поддерживается не во всех браузерах:источник
Беда с "контекстом"
Термин «контекст» иногда используется для обозначения объекта, на который ссылается это . Его использование является неуместным , поскольку он не соответствует ни семантически , ни технически с ECMAScript - х это .
«Контекст» означает обстоятельства, окружающие что-то, что добавляет значение, или некоторую предшествующую и следующую информацию, которая придает дополнительный смысл. Термин «контекст» используется в ECMAScript для обозначения контекста исполнения , который представляет собой все параметры, область действия и это в рамках некоторого исполняемого кода.
Это показано в разделе 10.4.2 ECMA-262 :
который ясно указывает на то, что это является частью контекста исполнения.
Контекст выполнения предоставляет окружающую информацию, которая добавляет смысл к исполняемому коду. Он включает в себя гораздо больше информации, чем просто thisBinding .
Таким образом, значение этого не «контекст», это просто одна часть контекста исполнения. По сути, это локальная переменная, которая может быть установлена при вызове любого объекта и в строгом режиме для любого значения вообще.
источник
this
но здесь он не предлагается, и, возможно, уже слишком поздно закрывать дверь для «контекста».Вы должны знать об этом ключевом слове.
На мой взгляд, вы можете реализовать «это» тремя способами (Self / Arrow function / Bind Method)
Ключевое слово this функции ведет себя немного иначе в JavaScript по сравнению с другими языками.
Он также имеет некоторые различия между строгим режимом и не строгим режимом.
В большинстве случаев значение этого определяется тем, как вызывается функция.
Он не может быть установлен присваиванием во время выполнения и может отличаться при каждом вызове функции.
ES5 представил метод bind () для установки значения функции this независимо от того, как она вызывается,
и ES2015 представили функции стрелок, которые не обеспечивают собственную привязку this (она сохраняет значение this лексического контекста).
Метод 1: Self - Self используется для сохранения ссылки на оригинал, даже если контекст меняется. Эта техника часто используется в обработчиках событий (особенно в замыканиях).
Ссылка : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Метод 2 : функция стрелки - выражение функции стрелки является синтаксически компактной альтернативой регулярному выражению функции,
хотя без привязок к ключевым словам this, arguments, super или new.target.
Выражения функций стрелок плохо подходят в качестве методов, и их нельзя использовать в качестве конструкторов.
Ссылка : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Метод 3 : Bind - метод bind () создает новую функцию, которая,
при вызове имеет ключевое слово this установленное значение,
с заданной последовательностью аргументов, предшествующей любому, предоставленному при вызове новой функции.
Ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
источник
Во-первых, вам необходимо иметь четкое понимание
scope
и поведениеthis
ключевых слов в контекстеscope
.this
&scope
:короче говоря, глобальная область действия относится к объекту окна. Переменные, объявленные в глобальной области видимости, доступны из любого места. С другой стороны, область действия функции находится внутри функции. Переменная, объявленная внутри функции, обычно не доступна из внешнего мира.
this
Ключевое слово в глобальной области действия относится к объекту окна.this
Внутренняя функция также ссылается на объект окна. Такthis
что всегда будем ссылаться на окно, пока мы не найдем способ манипулировать,this
чтобы указать контекст по нашему выбору.Различные способы манипулирования
this
внутри функций обратного вызова:Здесь у меня есть функция конструктора Person. Он имеет свойство
name
и четыре метода , называемогоsayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. У всех четырех из них есть одна конкретная задача. Принять обратный вызов и вызвать его. Обратный вызов имеет специальную задачу, которая заключается в регистрации свойства name экземпляра функции конструктора Person.Теперь давайте создадим экземпляр из конструктора person и вызовем разные версии метода
sayNameVersionX
(X относится к 1,2,3,4),niceCallback
чтобы увидеть, сколько способов мы можем манипулироватьthis
внутренним обратным вызовом для обращения кperson
экземпляру.связать:
Привязка заключается в создании новой функции с установленным значением
this
ключевого слова.sayNameVersion1
иsayNameVersion2
использовать связывание для управленияthis
функцией обратного вызова.первый связывается
this
с обратным вызовом внутри самого метода. А для второго передается обратный вызов с привязанным к нему объектом.вызов :
first argument
Отcall
метода используется какthis
внутри функции , которая вызывается сcall
прилагается к нему.sayNameVersion3
используетсяcall
для манипулированияthis
ссылкой на объект person, который мы создали, вместо объекта window.и это называется следующим образом:
применять :
Аналогично
call
, первый аргументapply
ссылки относится к объекту, который будет обозначенthis
ключевым словом.sayNameVersion4
используетapply
для манипулированияthis
ссылаться на объект человекаи это называется следующим образом. Просто обратный вызов передается,
источник
Мы не можем связать это с тем
setTimeout()
, как это всегда выполняется с глобальным объектом (Window) , если вы хотите получить доступ кthis
контексту в функции обратного вызова, то, используяbind()
функцию обратного вызова, мы можем добиться так:источник
Вопрос вращается вокруг того, как
this
ключевое слово ведет себя в JavaScript.this
ведет себя по-другому, как показано ниже,this
обычно определяется контекстом выполнения функции.this
ссылается на глобальный объект (window
объект).this
будет таким же,undefined
как в строгом режиме, глобальный объект ссылаетсяundefined
вместоwindow
объекта.call()
,bind()
иapply()
new
ключевое слово (конструктор), оно привязывается к создаваемому новому объекту.this
- вместо этого ониthis
связаны лексически (т.е. основаны на исходном контексте)Как подсказывает большинство ответов, мы можем использовать функцию Arrow или
bind()
Method или Self var. Я бы процитировал пункт о лямбдах (функция стрелки) из руководства по стилю Google JavaScriptGoogle явно рекомендует использовать лямбды, а не связывать или
const self = this
Таким образом, лучшее решение будет использовать лямбды, как показано ниже,
Ссылки:
источник
this
ключевого слова, поэтому я разделил свой ответ на две части, одну оthis
и вторую об использовании функций / методов в качестве обратных вызовов. Не стесняйтесь редактировать ответ.В настоящее время возможен другой подход, если в коде используются классы.
С поддержкой полей класса это можно сделать следующим образом:
Наверняка под капотом все старые добрые функции стрелок связывают контекст, но в этой форме это выглядит намного более ясно, чем явное связывание.
Поскольку это предложение этапа 3, вам понадобится babel и соответствующий плагин babel для его обработки, как сейчас (08/2018).
источник
public methodName = (params) => { body }
внутри класса.Другим подходом, который является стандартным способом связывания DOM2
this
внутри прослушивателя событий, позволяющим всегда удалять прослушиватель (среди других преимуществ), являетсяhandleEvent(evt)
метод изEventListener
интерфейса:Подробную информацию об использовании
handleEvent
можно найти здесь: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38источник
this
в JS:Значение
this
в JS на 100% определяется тем, как вызывается функция, а не тем, как она определена. Мы можем относительно легко найти значениеthis
по «правилу слева от точки» :this
является объект слева от точки вызываемой функцииthis
внутри функции часто является глобальным объектом (global
в узле,window
в браузере). Я бы не рекомендовал использоватьthis
здесь ключевое слово, потому что оно менее явное, чем что-то вродеwindow
!Function.prototype.bind()
функции, которая может фиксировать значениеthis
. Это исключения из правила, но они действительно помогают установить значениеthis
.Пример в nodeJS
Вывод:
Позвольте мне провести вас через выходы 1 на 1 (игнорируя первый журнал, начиная со второго):
this
этоobj2
из-за левой части правила точки, мы можем видеть, какtest1
называетсяobj2.test1();
.obj2
слева от точки и, следовательно,this
значения.obj2
что слева от точки,test2
связано сobj1
помощьюbind()
метода. Так чтоthis
ценность естьobj1
.obj2
находится слева от точки из функции , которая называется:obj2.test3()
. Поэтомуobj2
будет ценностьthis
.obj2.test4()
obj2
слева от точки. Однако функция стрелки не имеет собственнойthis
привязки. Поэтому он будет привязан кthis
значению внешнего объема, который являетсяmodule.exports
объектом, который был зарегистрирован в начале.this
с помощьюcall
функции. Здесь мы можем передать желаемоеthis
значение в качестве аргумента, чтоobj2
в данном случае.источник