Я заметил, что нет четкого объяснения того, что такое this
ключевое слово и как оно правильно (и неправильно) используется в JavaScript на сайте переполнения стека.
Я был свидетелем очень странного поведения с ним и не смог понять, почему это произошло.
Как this
работает и когда его следует использовать?
javascript
this
Максим Гершкович
источник
источник
this
peter.michaux.ca/articles/javascript-widgets-without-thisthis
ключевого слова: rainsoft.io/gentle-explanation-of-this-in-javascriptОтветы:
Я рекомендую сначала прочитать статью Майка Веста « Область применения в JavaScript ( зеркало )». Это отличное, дружественное введение в концепции
this
и области видимости в JavaScript.Как только вы начинаете привыкать
this
, правила на самом деле довольно просты. Стандарт ECMAScript 5.1 определяетthis
:ThisBinding - это то, что поддерживает интерпретатор JavaScript при оценке кода JavaScript, например, специальный регистр ЦП, который содержит ссылку на объект. Интерпретатор обновляет ThisBinding при установлении контекста выполнения только в одном из трех разных случаев:
1. Начальный глобальный контекст выполнения
Это относится к коду JavaScript, который оценивается на верхнем уровне, например, когда он находится непосредственно внутри
<script>
:При оценке кода в начальном глобальном контексте выполнения ThisBinding устанавливается на глобальный объект
window
( §10.4.1.1 ).Ввод электронного кода
… Прямым вызовом
eval()
ThisBinding остается без изменений; это то же значение, что и ThisBinding контекст вызывающего выполнения ( §10.4.2 (2) (a)).… Если не путем прямого вызова
eval()
ThisBinding, устанавливается глобальный объект, как если бы он выполнялся в начальном глобальном контексте выполнения ( §10.4.2 (1)).
§15.1.2.1.1 определяет, что такое прямой вызов
eval()
. По сути,eval(...)
это прямой вызов, тогда как нечто подобное(0, eval)(...)
илиvar indirectEval = eval; indirectEval(...);
косвенный вызовeval()
. Смотрите ответ Чака на (1, eval) ('this') против eval ('this') в JavaScript? и ECMA-262-5 Дмитрия Сошникова в деталях. Глава 2. Строгий режим. когда вы можете использовать косвенныйeval()
вызов.Ввод кода функции
Это происходит при вызове функции. Если функция вызывается для объекта, такого как in
obj.myMethod()
или его эквивалентobj["myMethod"]()
, тогда ThisBinding устанавливается на объект (obj
в примере; §13.2.1 ). В большинстве других случаев ThisBinding устанавливается на глобальный объект ( §10.4.3 ).Причина написания «в большинстве других случаев» заключается в том, что существует восемь встроенных функций ECMAScript 5, которые позволяют указывать ThisBinding в списке аргументов. Эти специальные функции принимают так называемое,
thisArg
которое становится ThisBinding при вызове функции ( §10.4.3 ).Эти специальные встроенные функции:
Function.prototype.apply( thisArg, argArray )
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
В случае
Function.prototype
функций они вызываются для объекта функции, но вместо установки ThisBinding для объекта функции ThisBinding устанавливается вthisArg
.В случае
Array.prototype
функций заданныйcallbackfn
вызывается в контексте выполнения, где ThisBinding установлен,thisArg
если предоставляется; в противном случае, к глобальному объекту.Это правила для простого JavaScript. Когда вы начинаете использовать библиотеки JavaScript (например, jQuery), вы можете обнаружить, что некоторые библиотечные функции манипулируют значением
this
. Разработчики этих библиотек JavaScript делают это, потому что это имеет тенденцию поддерживать наиболее распространенные варианты использования, и пользователи библиотеки обычно считают такое поведение более удобным. При передаче функций обратного вызова, ссылающихсяthis
на библиотечные функции, вы должны ссылаться на документацию для любых гарантий того, каково значение тогоthis
, когда вызывается функция.Если вам интересно, как библиотека JavaScript манипулирует значением
this
, библиотека просто использует одну из встроенных функций JavaScript, принимающих athisArg
. Вы также можете написать свою собственную функцию с функцией обратного вызова иthisArg
:Есть особый случай, о котором я еще не упомянул. При создании нового объекта с помощью
new
оператора интерпретатор JavaScript создает новый пустой объект, устанавливает некоторые внутренние свойства и затем вызывает функцию конструктора для нового объекта. Таким образом, когда функция вызывается в контексте конструктора, значениемthis
является новый объект, созданный интерпретатором:Функции стрелок
Функции стрелок (введенные в ECMA6) изменяют область действия
this
. Смотрите существующий канонический вопрос, функция Arrow против объявления / выражений функции: являются ли они эквивалентными / заменяемыми? за дополнительной информацией. Но вкратце:Просто для удовольствия, проверьте свое понимание с некоторыми примерами
Чтобы раскрыть ответы, наведите курсор мыши на светло-серые поля.
Какова стоимость
this
в отмеченной линии? Почему?Каково значение
this
в отмеченной строке, когдаobj.staticFunction()
выполняется? Почему?Какова стоимость
this
в отмеченной линии? Почему?Какова стоимость
this
в отмеченной линии? Почему?Какова стоимость
this
в отмеченной линии? Почему?источник
setTimeout
примере естьthis
оwindow(global)
.В
this
ключевых словах ведет себя по- разному в JavaScript по сравнению с другими языками. В объектно-ориентированных языкахthis
ключевое слово относится к текущему экземпляру класса. В JavaScript значениеthis
определяется контекстом вызова функции (context.function()
) и местом его вызова .1. При использовании в глобальном контексте
Когда вы используете
this
в глобальном контексте, он привязан к глобальному объекту (window
в браузере)Когда вы используете
this
внутри функции, определенной в глобальном контексте,this
все еще привязан к глобальному объекту, так как функция фактически сделана методом глобального контекста.Выше
f1
сделан метод глобального объекта. Таким образом, мы можем также вызвать его дляwindow
объекта следующим образом:2. При использовании внутри метода объекта
Когда вы используете
this
ключевое слово внутри метода объекта,this
привязывается к «непосредственному» включающему объекту.Выше я поставил слово сразу в двойных кавычках. Следует подчеркнуть, что если вы вложите объект в другой объект, он
this
будет связан с непосредственным родителем.Даже если вы добавляете функцию явно к объекту как метод, она все равно следует вышеприведенным правилам, то есть
this
указывает на непосредственный родительский объект.3. При вызове функции без контекста
Когда вы используете
this
внутреннюю функцию, которая вызывается без какого-либо контекста (т.е. не для какого-либо объекта), она привязывается к глобальному объекту (window
в браузере) (даже если функция определена внутри объекта).Попытка все это с функциями
Мы можем попробовать вышеуказанные пункты с функциями тоже. Однако есть некоторые различия.
this
. указать их.new
оператора.Ниже я опробовал все то, что мы сделали с Object и
this
выше, но сначала создав функцию вместо прямой записи объекта.4. При использовании внутри функции конструктора .
Когда функция используется в качестве конструктора (то есть когда она вызывается с
new
ключевым словом),this
внутри тела функции указывается на создаваемый новый объект.5. При использовании внутри функции, определенной в цепочке прототипов
Если метод находится в цепочке прототипов объекта,
this
внутри такого метода указывается объект, к которому был вызван метод, как если бы метод был определен для объекта.6. Внутри функций call (), apply () и bind ()
Function.prototype
.this
которое будет использоваться во время выполнения функции. Они также принимают любые параметры, которые будут переданы исходной функции, когда она вызывается.fun.apply(obj1 [, argsArray])
Устанавливаетobj1
в качестве значенияthis
insidefun()
и вызываетfun()
передаваемые элементы вargsArray
качестве аргументов.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Устанавливаетobj1
в качестве значенияthis
insidefun()
и вызываетfun()
передачу вarg1, arg2, arg3, ...
качестве аргументов.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Возвращает ссылку на функциюfun
сthis
привязкой внутри funobj1
и параметрамиfun
привязки к указанным параметрамarg1, arg2, arg3,...
.apply
,call
иbind
должно быть , стало очевидным.apply
позволяет указывать аргументы для работы в виде массива, например объекта с числовымlength
свойством и соответствующими неотрицательными целочисленными свойствами. Принимая во внимание, чтоcall
позволяет указывать аргументы функции напрямую. И то,apply
и другоеcall
немедленно вызывает функцию в указанном контексте и с указанными аргументами. С другой стороны,bind
просто возвращает функцию, связанную с указаннымthis
значением и аргументами. Мы можем захватить ссылку на эту возвращенную функцию, присвоив ее переменной, и позже мы можем вызвать ее в любое время.7.
this
внутри обработчики событийthis
непосредственно внутри функции обработки событий ссылается на соответствующий элемент. Такое прямое назначение функции может быть выполнено с использованиемaddeventListener
метода или с помощью традиционных методов регистрации событий, таких какonclick
.this
непосредственно внутри свойства события (например<button onclick="...this..." >
) элемента, оно ссылается на элемент.this
косвенно через другую функцию, вызываемую внутри функции обработки события или свойства события, разрешается глобальным объектомwindow
.attachEvent
. Вместо того, чтобы назначать функцию обработчику события (и, таким образом, создавать метод функции элемента), она вызывает функцию для события (фактически вызывая ее в глобальном контексте).Я рекомендую лучше попробовать это в JSFiddle .
8.
this
в функции стрелки ES6В функции стрелки
this
будет вести себя как общие переменные: она будет унаследована от своей лексической области видимости. Функцииthis
, в которых определена функция стрелки, будут функциями стрелкиthis
.Итак, это то же поведение, что и:
Смотрите следующий код:
источник
this
не устанавливается вызовом. Поскольку код не находится в строгом режиме, значениеthis
всегда должно быть объектом, поэтому по умолчанию используется глобальный объект. И на самом деле именно поэтому я подумал, что мы можем напрямую сделать вызовwindow.f1()
, так что средствоf1()
уже прикреплено кwindow
объекту, я имею в виду до вызова. Я неправильно понял?window.fn
, но это не так. по умолчанию это глобальный объект, потому что в вызове не использовалась базовая ссылка, а не из-за того, где определена функция (так что это все равно устанавливается тем, как была вызвана функция). Если вы явно вызываете его с помощьюwindow.fn
, то вы устанавливаете это в окно . Тот же результат, другой способ сделать это. :-)в JavaScript
this
Простой вызов функции
Рассмотрим следующую функцию:
Обратите внимание, что мы запускаем это в обычном режиме, то есть строгий режим не используется.
При запуске в браузере значение
this
будет зарегистрировано какwindow
. Это потому, чтоwindow
это глобальная переменная в области видимости веб-браузера.Если вы запустите этот же кусок кода в среде, такой как node.js,
this
то будете ссылаться на глобальную переменную в вашем приложении.Теперь, если мы запустим это в строгом режиме, добавив оператор
"use strict";
в начало объявления функции, мыthis
больше не будем ссылаться на глобальную переменную ни в одной из сред. Это сделано, чтобы избежать путаницы в строгом режиме.this
будет, в этом случае просто войтиundefined
, потому что это то, что он есть, он не определен.В следующих случаях мы увидим, как манипулировать значением
this
.Вызов функции на объекте
Есть разные способы сделать это. Если вы вызывали нативные методы в Javascript, например,
forEach
иslice
, вы уже должны знать, чтоthis
переменная в этом случае ссылаетсяObject
на ту функцию, для которой вы вызвали эту функцию (обратите внимание, что в javascript практически все являетсяObject
, включаяArray
s иFunction
s). Возьмите следующий код для примера.Если an
Object
содержит свойство, которое содержитFunction
, свойство называется методом. Этот метод, при вызове, всегда будет иметь своюthis
переменную равной тому, с которойObject
он связан. Это верно как для строгих, так и для нестрогих режимов.Обратите внимание, что если метод хранится (или, скорее, копируется) в другой переменной, ссылка на
this
более не сохраняется в новой переменной. Например:Рассматривая более практичный сценарий:
new
ключевое словоРассмотрим функцию конструктора в Javascript:
Как это работает? Что ж, посмотрим, что произойдет, когда мы используем
new
ключевое слово.new
ключевым словом немедленно инициализируетObject
типPerson
.Object
имеет свой конструктор установлен вPerson
. Кроме того, обратите внимание,typeof awal
что вернетсяObject
только.Object
будет присвоен прототипPerson.prototype
. Это означает, что любой метод или свойство вPerson
прототипе будет доступно для всех экземпляровPerson
, включаяawal
.Person
теперь вызывается;this
быть ссылкой на недавно построенный объектawal
.Довольно просто, а?
Обратите внимание, что в официальной спецификации ECMAScript нигде не говорится, что такие типы функций являются фактическими
constructor
функциями. Они являются просто обычными функциями иnew
могут использоваться в любой функции. Просто мы используем их как таковые, и поэтому мы называем их только таковыми.Вызов функций на функции:
call
иapply
Так что да, поскольку
function
s такжеObjects
(и фактически переменные первого класса в Javascript), даже функции имеют методы, которые ... ну, сами функции.Все функции наследуются от глобального
Function
, и два из его многочисленных методов - этоcall
иapply
, и оба могут использоваться для манипулирования значениемthis
функции, для которой они вызываются.Это типичный пример использования
call
. Это в основном принимает первый параметр и устанавливаетthis
в функциюfoo
в качестве ссылки наthisArg
. Все остальные передаваемые параметры передаютсяcall
функции вfoo
качестве аргументов.Таким образом, приведенный выше код войдет
{myObj: "is cool"}, [1, 2, 3]
в консоль. Довольно приятный способ изменить значениеthis
в любой функции.apply
почти так же, какcall
принять, что он принимает только два параметра:thisArg
и массив, который содержит аргументы для передачи в функцию. Таким образом, приведенный вышеcall
вызов можно перевестиapply
так:Обратите внимание, что
call
иapply
может переопределить значениеthis
вызова метода точка путем, который мы обсуждали во втором пункте. Достаточно просто :)Представляя ....
bind
!bind
это братcall
иapply
. Это также метод, унаследованный всеми функциями от глобальногоFunction
конструктора в Javascript. Разница междуbind
иcall
/apply
заключается в том, что обаcall
иapply
фактически вызовут функцию.bind
, С другой стороны, возвращает новую функцию сthisArg
иarguments
заранее заданными параметрами. Давайте рассмотрим пример, чтобы лучше понять это:Видите разницу между тремя? Это тонко, но они используются по-разному. Как
call
иapply
,bind
также переопределит значение,this
установленное вызовом точечного метода.Также обратите внимание, что ни одна из этих трех функций не изменяет исходную функцию.
call
иapply
будет возвращать значение из только что созданных функций, в то время какbind
будет возвращать саму недавно созданную функцию, готовую к вызову.Дополнительные вещи, скопируйте это
Иногда вам не нравится тот факт, что
this
меняется с областью, особенно вложенной области. Посмотрите на следующий пример.В приведенном выше коде мы видим, что значение
this
изменилось с вложенной областью действия, но мы хотели получить значениеthis
из исходной области действия. Таким образом , мы «скопировано»this
вthat
и используется копия вместоthis
. Умно, а?Индекс:
this
по умолчанию?new
ключевое слово?this
сcall
иapply
?bind
.this
для решения проблем вложенных областей.источник
«это» все о сфере. Каждая функция имеет свою область видимости, и поскольку все в JS является объектом, даже функция может сохранять некоторые значения в себе, используя «this». ООП 101 учит, что «это» применимо только к экземплярам объекта. Поэтому каждый раз, когда функция выполняется, новый «экземпляр» этой функции имеет новое значение «this».
Большинство людей смущаются, когда пытаются использовать «this» внутри анонимных функций закрытия, таких как:
Так что здесь, внутри each (), «this» не содержит «значение», которого вы ожидаете (от
над ним). Таким образом, чтобы преодолеть эту (не каламбур) проблему, разработчик может:Попробуйте это; вы начнете любить эту модель программирования
источник
this
Ключевое слово не имеет ничего общего с размахом. Кроме того, это имеет значение также в функциях, которые не являются свойствами объектов.this
это не все о сфере. Это ВСЕ о контексте выполнения, который отличается от контекста. JavaScript имеет лексическую область действия (то есть область действия определяется местоположением кода), ноthis
определяется тем, как вызывается функция, в которой он содержится, а не тем, где находится эта функция.Так как эта тема увеличилась, я собрал несколько пунктов для читателей, плохо знакомых с этой
this
темой.Как определяется стоимость
this
?Мы используем это подобно тому, как мы используем местоимения на естественных языках, таких как английский: «Джон быстро бегает, потому что пытается сесть на поезд». Вместо этого мы могли бы написать «… Джон пытается сесть на поезд».
this
не присваивается значение, пока объект не вызовет функцию, в которой он определен. В глобальной области видимости все глобальные переменные и функции определены дляwindow
объекта. Следовательно,this
в глобальной функции ссылается (и имеет значение) глобальныйwindow
объект.Когда
use strict
,this
в глобальном , так и в анонимных функциях, которые не связаны с каким - либо объектом имеет значениеundefined
.this
Ключевое слово наиболее неправильно , когда: 1) заимствовать метод , который используетthis
, 2) назначить метод , который используетthis
на переменный, 3) функции , которая используетthis
передаются в качестве функции обратного вызова, и 4)this
используются внутри крышки - внутренняя функция. (2)Что держит будущее
Определяемые в скрипте ECMA 6 , функции-стрелки принимают
this
привязку из внешней (функциональной или глобальной) области видимости.Хотя функции-стрелки предоставляют альтернативу использованию
bind()
, важно отметить, что они по существу отключают традиционныйthis
механизм в пользу более широко понятого лексического определения объема. (1)Ссылки:
источник
this
в JavaScript всегда относится к «владельцу» функции, которая выполняется .Если явный владелец не определен, то указывается самый верхний владелец, объект окна.
Так что если бы я сделал
element.onclick = someKindOfFunction;
this
будет относиться к элементу объекта. Но будьте осторожны, многие люди совершают эту ошибку.<element onclick="someKindOfFunction()">
В последнем случае вы просто ссылаетесь на функцию, а не передаете ее элементу. Следовательно,
this
будем ссылаться на объект окна.источник
Каждый контекст выполнения в javascript имеет параметр this, который устанавливается:
eval
Вы можете установить значение этого с помощью
func.call
,func.apply
илиfunc.bind
.По умолчанию, и что смущает большинство новичков, когда слушатель вызывается после того, как событие вызвано в элементе DOM, значение this функции является элементом DOM.
jQuery делает это тривиальным, чтобы изменить с jQuery.proxy.
источник
this
в Javascript то, что это не внутреннее свойство самой функции, а скорее артефакт того, как вызывается функция.func.call
, иfunc.bind
т.д. - Sushilthis
никак не ссылаться на область действия функции.this
будет ссылаться на конкретный объект (или, возможно,undefined
), который, как вы сказали, можно изменить с помощью.call()
или.apply()
. Область действия функции (по сути, когда она упрощена), к каким переменным она имеет доступ, и это полностью зависит от того, где функция объявлена и не может быть изменена.this
и область действия не имеет ничего общего друг с другом в ES5 и ранее (например, когда этот ответ был написан). В ES2015 (он же ES6)this
и область видимости связаны одним довольно минимальным способом с функциями стрелок (функцияthis
in arrow наследуется от включающей области видимости), ноthis
никогда не ссылается на область.Вот один хороший источник
this
вJavaScript
.Вот резюме:
глобальный это
В браузере, в глобальном масштабе,
this
являетсяwindow
объектомПри
node
использовании repl,this
это верхнее пространство имен. Вы можете сослаться на это какglobal
.При
node
выполнении из скриптаthis
глобальная область видимости начинается как пустой объект. Это не то же самое, чтоglobal
функция это
За исключением случаев для обработчиков событий DOM или когда
thisArg
предоставляется a (см. Далее), как в узле, так и в браузере, используяthis
функцию, которая не вызывается соnew
ссылками на глобальную область видимости…Если вы используете
use strict;
, в каком случаеthis
будетundefined
При вызове функции с
new
вthis
будет новым контекстом, он не будет ссылаться на глобальномthis
.Создаваемые вами функции становятся объектами функций. Они автоматически получают специальное
prototype
свойство, которому вы можете присвоить значения. Когда вы создаете экземпляр, вызывая свою функцию,new
вы получаете доступ к значениям, которые вы присвоилиprototype
свойству. Вы получаете доступ к этим значениям, используяthis
.Обычно ошибочно назначать массивы или объекты в
prototype
. Если вы хотите, чтобы экземпляры имели свои собственные массивы, создайте их в функции, а не в прототипе.Вы можете использовать
this
любую функцию объекта для ссылки на другие свойства этого объекта. Это не то же самое, что экземпляр, созданный с помощьюnew
.В обработчике событий HTML DOM
this
всегда указана ссылка на элемент DOM, к которому было прикреплено событиеЕсли вы не
bind
контекстВнутри атрибутов HTML, в которые можно поместить JavaScript,
this
есть ссылка на элемент.Вы можете использовать
eval
для доступаthis
.Вы можете использовать
with
для добавленияthis
в текущую область, чтобы читать и записывать значения,this
не ссылаясьthis
явно.Во многих местах jQuery
this
ссылается на элемент DOM.источник
Даниэль, классное объяснение! Пара слов об этом и хороший список
this
указателей контекста выполнения в случае обработчиков событий.В двух словах,
this
в JavaScript указывается объект, от которого (или из чьего контекста выполнения) была запущена текущая функция, и она всегда доступна только для чтения, в любом случае вы не можете установить ее (такая попытка будет заканчиваться «Неверный левой рукой»). сторона в сообщении присваивания.Для обработчиков событий: встроенные обработчики событий, такие как
<element onclick="foo">
, переопределяют любые другие обработчики, присоединенные ранее и ранее, поэтому будьте осторожны, и лучше вообще избегать делегирования встроенных событий. И спасибо Zara Alaverdyan, которая вдохновила меня на этот список примеров через несогласные дебаты :)el.onclick = foo; // in the foo - obj
el.onclick = function () {this.style.color = '#fff';} // obj
el.onclick = function() {doSomething();} // In the doSomething - Window
el.addEventListener('click',foo,false) // in the foo - obj
el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
<button onclick="this.style.color = '#fff';"> // obj
<button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
источник
Существует много путаницы в отношении того, как это ключевое слово интерпретируется в JavaScript. Надеюсь, эта статья положит конец всем раз и навсегда. И многое другое. Пожалуйста, внимательно прочитайте всю статью. Будьте предупреждены, что эта статья длинная.
Независимо от контекста, в котором он используется, «this» всегда ссылается на «текущий объект» в Javascript. Однако то, чем является «текущий объект», зависит от контекста . Контекст может быть точно 1 из 6 следующих:
Следующее описывает каждый из этих контекстов один за другим:
Глобальный контекст (т.е. вне всех функций):
Вне всех функций (т. Е. В глобальном контексте) «текущий объект» (и, следовательно, значение «this» ) всегда является объектом «окна» для браузеров.
Внутренний прямой вызов «Не связанная функция» :
Внутри прямого вызова «Не связанная функция» объект, вызвавший вызов функции, становится «текущим объектом» (и, следовательно, значением «this» ). Если функция вызывается без явного текущего объекта , текущий объект является либо «оконным» объектом (для нестрого режима), либо неопределенным (для строгого режима). Любая функция (или переменная), определенная в глобальном контексте, автоматически становится свойством объекта «окно». Например, предположим, что функция определяется в глобальном контексте как
оно становится свойством объекта окна, как если бы вы определили его как
В «Non Strict Mode», вызов / Вызов этой функции непосредственно через «UserDefinedFunction ()» будет автоматически вызывать / ссылаться на него , как «window.UserDefinedFunction ()» делает «окно» , как «текущий объект» (и , следовательно , значение " this " ) внутри " UserDefinedFunction ". Вызов этой функции в" не строгом режиме "приведет к следующему
В «Строгом режиме» вызов / вызов функции напрямую через «UserDefinedFunction ()» будет «НЕ» автоматически вызывать / вызывать ее как «window.UserDefinedFunction ()». Подразумевает «текущий объект» (и значение «this» ) внутри "UserDefinedFunction" должно быть неопределенным . Вызов этой функции в «Строгом режиме» приведет к следующему
Однако его явный вызов с использованием объекта window должен привести к следующему
Давайте посмотрим на другой пример. Пожалуйста, посмотрите на следующий код
В приведенном выше примере мы видим, что когда «UserDefinedFunction» вызывался через o1 , «this» принимает значение o1, и отображаются значения его свойств «a» и «b» . Значения "c" и "d" были показаны как неопределенные, поскольку o1 не определяет эти свойства
Точно так же , когда «UserDefinedFunction» был вызван через o2 , «этот» принимает значение o2 и значение его свойства «в» и «г» получить displayed.The значение «а» и «б» было показано , как определено , как о2 делает не определять эти свойства.
Внутри косвенного вызова «Не связанная функция» вызов через functionName.call и functionName.apply :
Когда «Non Bound Function» вызывается через functionName.call или functionName.apply , «текущий объект» (и, следовательно, значение «this» ) устанавливается равным значению параметра «this» (первого параметра), передаваемого для вызова / применить . Следующий код демонстрирует то же самое.
Приведенный выше код ясно показывает, что значение «this» для любой «NON Bound Function» может быть изменено с помощью call / apply . Кроме того, если параметр «this» явно не передан в call / apply , «текущий объект» (и, следовательно, значение «this») устанавливается в «window» в нестрогом режиме и «undefined» в строгом режиме.
Внутри вызова «Связанная функция» (то есть функция, которая была связана вызовом functionName.bind ):
Связанная функция - это функция, значение которой this было зафиксировано. Следующий код демонстрирует, как работает «this» в случае связанной функции
Как указано в коде выше, «this» для любой «Связанной функции» НЕ МОЖЕТ быть изменено посредством вызова / применения . Кроме того, если параметр «this» не передан явно для привязки, «текущий объект» (и, следовательно, значение «this» ) устанавливается в «window» в нестрогом режиме и «undefined» в строгом режиме. Еще кое-что. Привязка уже связанной функции не меняет значение «this» . Он остается установленным в качестве значения, установленного первой функцией связывания.
При создании объекта через «новый» :
Внутри функции конструктора «текущий объект» (и, следовательно, значение «этого» ) ссылается на объект, который в данный момент создается через «новый», независимо от состояния привязки функции. Однако, если конструктор является связанной функцией, он должен вызываться с предопределенным набором аргументов, установленным для связанной функции.
Внутри встроенного обработчика событий DOM :
Пожалуйста, посмотрите на следующий фрагмент HTML
«Это» в приведенном выше примеры относятся к элементу «Кнопки» и элементу «сОн» соответственно.
В первом примере цвет шрифта кнопки должен быть установлен белым при нажатии.
Во втором примере при щелчке элемента «div» он должен вызвать функцию OnDivClick, второй параметр которой ссылается на элемент div, по которому щелкнули. Однако значение «this» в OnDivClick НЕ ДОЛЖНО ссылаться на нажатый элемент div . Он должен быть установлен как «объект окна» или «неопределенный» в нестрогом и строгом режимах соответственно (если OnDivClick является несвязанной функцией ) или установлен в предварительно определенное значение Bound (если OnDivClick является связанной функцией )
Следующее суммирует всю статью
В глобальном контексте «это» всегда относится к объекту «окна»
Всякий раз, когда вызывается функция, она вызывается в контексте объекта ( «текущий объект» ). Если текущий объект явно не указан, текущий объект является «оконным объектом» в строгом режиме и не определен в строгом режиме по умолчанию.
Значение «this» в функции Non Bound является ссылкой на объект, в контексте которого вызывается функция ( «текущий объект» )
Значение «это» в функции Non Bound может быть переопределено вызовом и применением методов функции.
Значение «this» является фиксированным для функции Bound и не может быть переопределено вызовом и применением методов функции.
Привязка и уже связанная функция не изменяют значение «this». Он остается установленным в качестве значения, установленного первой функцией связывания.
Значение «this» в конструкторе - это объект, который создается и инициализируется
Значение «this» в встроенном обработчике событий DOM является ссылкой на элемент, для которого предоставляется обработчик события.
источник
Вероятно, самая подробная и всеобъемлющая статья о
this
следующем:Нежное объяснение ключевого слова this в JavaScript
Идея
this
заключается в том, чтобы понять, что типы вызова функций имеют большое значение для установкиthis
значения.Если возникают проблемы с выявлением
this
, не спрашивайте себя:но действительно спросить себя:
Для функции стрелки (особый случай прозрачности контекста) спросите себя:
Такое мышление является правильным при работе с
this
и избавит вас от головной боли.источник
this
ключевое слово?Это лучшее объяснение, которое я видел: понять JavaScripts это с Clarity
Существует четыре сценария, в которых это может сбить с толку:
Он приводит примеры кода, объяснения и решения, которые, на мой взгляд, были очень полезны.
источник
В псевдоклассических терминах, во многих лекциях учат ключевое слово «this», это как объект, созданный классом или конструктором объекта. Каждый раз, когда новый объект создается из класса, представьте, что под капотом создается и возвращается локальный экземпляр объекта this. Я помню, этому учили так:
источник
this
это одна из неправильно понятых концепций в JavaScript, потому что она ведет себя немного по-разному в разных местах. Проще говоря,this
относится к «владельцу» функции, которую мы в настоящее время выполняем .this
помогает получить текущий объект (или контекст выполнения), с которым мы работаем. Если вы понимаете , в какой объект текущая функция становится выполнена, вы можете легко понять , какие текущиеthis
ISВыше мы создаем 3 переменные с тем же именем 'val'. Один в глобальном контексте, один внутри obj, а другой внутри innerMethod of obj. JavaScript разрешает идентификаторы в определенном контексте, перемещаясь по цепочке областей действия от локального выхода к глобальному.
Несколько мест, где
this
можно выделитьВызов метода объекта
Когда line1 выполняется, JavaScript устанавливает контекст выполнения (EC) для вызова функции, установка
this
на объект , на который ссылается то , что было до последнего «» , так что в последней строке вы можете понять, чтоa()
было выполнено в глобальном контексте, который являетсяwindow
.С конструктором
this
может использоваться для ссылки на создаваемый объектКогда
Person()
выполняется новый , создается совершенно новый объект.Person
вызывается, и егоthis
устанавливается для ссылки на этот новый объект.Вызов функции
Если мы пропустим
new
ключевое слово,whatIsThis
ссылаемся на самый глобальный контекст, который он может найти (window
)С обработчиками событий
Если обработчик события встроен,
this
ссылается на глобальный объектПри добавлении обработчика события через JavaScript,
this
ссылается на элемент DOM, который сгенерировал событие..apply()
.call()
и.bind()
var that = this
значит в JavaScriptисточник
Значение this зависит от контекста, в котором выполняется функция. Контекст может быть любым объектом или глобальным объектом, то есть окном.
Так что Семантика «этого» отличается от традиционных языков ООП. И это вызывает проблемы: 1. когда функция передается другой переменной (скорее всего, обратному вызову); и 2. когда замыкание вызывается из метода-члена класса.
В обоих случаях это установлено в окно.
источник
Как это может помочь? (Большая путаница с «этим» в javascript связана с тем, что он, как правило, связан не с вашим объектом, а с текущей областью выполнения - это может быть не совсем так, как это работает, но мне всегда кажется, что это так - см. статью для полного объяснения)
источник
Немного информации об этом ключевом слове
Давайте зарегистрируем
this
ключевое слово на консоли в глобальной области видимости без кода, ноВ Client / Browser
this
ключевое слово - это глобальный объект, которыйwindow
а также
В Server / Node / Javascript
this
ключевое слово времени выполнения также является глобальным объектом, которыйmodule.exports
Имейте в виду,
exports
это просто ссылка наmodule.exports
источник
это использование для Scope так же, как это
Значения txt1 и txt одинаковы. В приведенном выше примере $ (this) = $ ('# tbleName tbody tr') равно
источник
У меня другой взгляд на
this
к другим ответам, которые, я надеюсь, будут полезны.Один из способов взглянуть на JavaScript - это увидеть только 1 способ вызова функции 1 . это
Всегда есть какая-то ценность для
objectForThis
.Все остальное является синтаксическим сахаром для
functionObject.call
Итак, все остальное можно описать тем, как оно переводится на
functionObject.call
.Если вы просто вызываете функцию, то
this
это «глобальный объект», который в браузере является окномДругими словами,
был эффективно переведен на
Обратите внимание, что если вы используете строгий режим, то
this
будетundefined
что значит
Другими словами,
был эффективно переведен на
В JavaScript есть операторы типа
+
и-
и*
. Существует также точка оператора, который.
.
Оператора при использовании функции справа и объекта слева фактически означает «объект в качестве проходаthis
к функции.пример
Другими словами,
bar.foo()
переводится наconst temp = bar.foo; temp.call(bar);
Обратите внимание, что не имеет значения, как была создана функция (в основном ...). Все это даст одинаковые результаты
Опять же, все это просто синтаксический сахар для
Еще одна складка - прототип цепи. При использовании
a.b
JavaScript сначала выполняется поиск объекта, на который ссылается непосредственноa
свойствоb
. Еслиb
объект не найден, JavaScript будет искать в прототипе объекта, чтобы найтиb
.Существуют различные способы определения прототипа объекта, наиболее распространенным в 2019 году является
class
ключевое слово. Для целей,this
хотя это не имеет значения. Важно то, что, когда он ищет в объектеa
свойство,b
если он находит свойствоb
в объекте или в цепочке прототипов, если вb
итоге оказывается функцией, то применяются те же правила, что и выше.b
Ссылки на функции будут вызываться с использованиемcall
метода и передачиa
как objectForThis, как показано в верхней части этого ответа.Сейчас же. Давайте представим, что мы создаем функцию, которая явно устанавливает
this
перед вызовом другой функции, а затем вызываем ее с помощью.
оператора (точка)После перевода использовать
call
,obj.bar()
становитсяconst temp = obj.bar; temp.call(obj);
. Когда мы входим вbar
функцию, которую мы вызываемfoo
но мы явно передаем другой объект для objectForThis, поэтому, когда мы приходим к foothis
, этот внутренний объект.Это то, что эффективно делают
bind
и=>
функции, и функции. Они более синтаксические сахара. Они эффективно создают новую невидимую функцию в точности какbar
выше, которая явно устанавливаетthis
перед вызовом любую указанную функцию. В случае bindthis
устанавливается то, что вы передаетеbind
.Обратите внимание, что если
functionObject.bind
бы не существовало, мы могли бы сделать свое собственное, как этои тогда мы могли бы назвать это так
Функции стрелки,
=>
оператор синтаксический сахар для привязкитакой же как
Точно так же
bind
, создается новая невидимая функция, которая вызывает данную функцию со связанным значением,objectForThis
но в отличиеbind
от объекта, который должен быть связан, является неявным. Это что угодноthis
происходит, когда=>
оператор используется.Итак, как и правила выше
obj.foo()
переводит,const temp = obj.foo; temp.call(obj);
что означает, что оператор стрелки внутриfoo
будет связыватьсяobj
с новой невидимой функцией и возвращать ту новую невидимую функцию, которая назначенаb
.b()
будет работать как всегдаb.call(window)
илиb.call(undefined)
вызывать новую невидимую функцию, которая былаfoo
создана. Эта невидимая функция игнорируетthis
переданные в нее и передаетobj
как objectForThis` в функцию стрелки.Код выше переводится как
1
apply
- другая функция, аналогичнаяcall
Но с ES6 концептуально вы можете даже перевести это на
источник
Резюме
this
Javascript:this
определяется тем, как функция вызывается не там, где она была создана!this
определяется объектом, который находится слева от точки. (window
в глобальном пространстве)this
ссылается на элемент DOM, для которого было вызвано событие.new
ключевым словом значениеthis
ссылается на вновь созданный объектthis
с функциями:call
,apply
,bind
Пример:
Пример слушателей событий:
Пример конструктора:
источник
Чтобы правильно понять «это», нужно понимать контекст, сферу и разницу между ними.
Область действия : в области видимости javascript связана с видимостью переменных, область видимости достигается за счет использования функции. (Узнайте больше о сфере)
Контекст : контекст связан с объектами. Это относится к объекту, которому принадлежит функция. Когда вы используете ключевое слово «this» в JavaScript, оно относится к объекту, которому принадлежит функция. Например, внутри функции, когда вы говорите: «this.accoutNumber», вы ссылаетесь на свойство «accoutNumber», которое принадлежит объекту, которому принадлежит эта функция.
Если у объекта «myObj» есть метод «getMyName», то когда ключевое слово «this» в JavaScript используется внутри «getMyName», он ссылается на «myObj». Если функция «getMyName» выполнялась в глобальной области видимости, то «this» относится к объекту окна (кроме строгого режима).
Теперь давайте посмотрим на пример:
Runnig abobve код в выводе браузера будет:
В соответствии с выводом, который вы находитесь внутри контекста объекта окна, также видно, что прототип окна ссылается на объект.
Теперь давайте попробуем внутри функции:
Вывод:
Вывод тот же, потому что мы зарегистрировали переменную this в глобальной области видимости и записали ее в функциональной области, мы не изменили контекст. В обоих случаях контекст был один и тот же, связанный с вдовьим объектом .
Теперь давайте создадим наш собственный объект. В javascript вы можете создавать объекты разными способами.
Вывод:
Таким образом, из приведенного выше примера мы обнаружили, что ключевое слово «this» относится к новому контексту, связанному с myObj, и myObject также имеет цепочку прототипов для Object.
Пойдем кинем еще один пример:
вывод: имеет смысл правильно? (читать комментарии)
Если у вас возникли проблемы с пониманием приведенного выше примера, давайте попробуем воспользоваться нашим собственным обратным вызовом;
вывод:
Теперь давайте разберемся в Scope, Self, IIFE и THIS, как ведет себя
Вывод довольно классный, верно?
источник
Простой ответ:
Это ключевое слово всегда зависит от контекста вызова. Они упомянуты ниже.
ФУНКЦИЯ ВЫЗЫВАЕТСЯ С НОВЫМ КЛЮЧОМ
Если функция вызывается с ключевым словом NEW, тогда THIS будет привязан к вновь созданному объекту.
Выше это будет связано с объектом 'myCar'
ФУНКЦИЯ ВЫЗЫВАЕТСЯ ТОЛЬКО С ИСПОЛЬЗОВАНИЕМ МЕТОДОВ ВЫЗОВА И ПРИМЕНЕНИЯ.
В этом случае ЭТО будет связано с объектом, который явно передается функции.
ЕСЛИ ФУНКЦИЯ ВЫЗЫВАЕТСЯ С ОБЪЕКТОМ, ТОЛЬКО ПОСЛЕ ТОГО, ЧТО ЭТО БУДЕТ СВЯЗАНО С ЭТИМ ОБЪЕКТОМ
КОГДА ФУНКЦИЯ ВЫЗВАНА БЕЗ ЛЮБОГО КОНТЕКСТА, ЭТО БУДЕТ СВЯЗАНО С ГЛОБАЛЬНЫМ ОБЪЕКТОМ
В СТРОГО РЕЖИМЕ ЭТО БУДЕТ НЕ УКАЗАНО
источник