Как работает ключевое слово "this"?
Я заметил, что, похоже, нет четкого объяснения того, что такое ключевое слово this
и как оно правильно (и неправильно) используется в JavaScript.
Я наблюдал за этим очень странное поведение и не понял, почему это произошло.
Как работает this
и когда он должен использоваться?
Ответы
Ответ 1
Я рекомендую сначала прочитать статью Майка Уэста Scope на JavaScript (зеркало). Это отличное, дружественное введение в концепции this
и цепочки областей действия в JavaScript.
Как только вы начинаете привыкать к this
, правила на самом деле довольно просты. Стандарт ECMAScript 5.1 определяет this
:
§11.1.1 Ключевое слово this
Ключевое слово this
оценивает значение ThisBinding текущего контекста выполнения.
ThisBinding - это то, что поддерживает интерпретатор JavaScript при оценке кода JavaScript, например, специальный регистр ЦП, который содержит ссылку на объект. Интерпретатор обновляет ThisBinding каждый раз, когда устанавливает контекст выполнения только в одном из трех разных случаев:
1. Начальный глобальный контекст выполнения
Это касается кода JavaScript, который оценивается на верхнем уровне, например, когда он находится непосредственно внутри <script>
:
<script>
alert("I'm evaluated in the initial global execution context!");
setTimeout(function () {
alert("I'm NOT evaluated in the initial global execution context.");
}, 1);
</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(...);
var indirectEval = eval; indirectEval(...);
это косвенный вызов eval()
. Смотрите ответ chuckj на (1, eval) ('this') против eval ('this') в JavaScript? и Дмитрий Сошниковых ECMA-262-5 в деталях. Глава 2. Строгий режим. когда вы можете использовать косвенный вызов eval()
.
Ввод кода функции
Это происходит при вызове функции. Если функция вызывается для объекта, например, в 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, принимающих thisArg
. Вы также можете написать свою собственную функцию с функцией обратного вызова и thisArg
:
function doWork(callbackfn, thisArg) {
//...
if (callbackfn != null) callbackfn.call(thisArg);
}
Это особый случай, о котором я еще не упомянул. При создании нового объекта с помощью оператора new
интерпретатор JavaScript создает новый пустой объект, устанавливает некоторые внутренние свойства и затем вызывает функцию конструктора для нового объекта. Таким образом, когда функция вызывается в контексте конструктора, значением this
является новый объект, созданный интерпретатором:
function MyType() {
this.someData = "a string";
}
var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);
Функции стрелок
Функции стрелок (введенные в ECMA6) изменяют объем this
. См. Существующий канонический вопрос: функция Arrow против объявления/выражений функции: являются ли они эквивалентными/заменяемыми? для дополнительной информации. Но вкратце:
Функции стрелки не имеют свои собственные this
.... переплета. Вместо этого эти идентификаторы разрешаются в лексической области, как и любая другая переменная. Это означает, что внутри функции стрелки this
... ссылается на значения this
в среде, в которой определена функция стрелки.
Просто для удовольствия, проверьте свое понимание с некоторыми примерами
Чтобы раскрыть ответы, наведите курсор мыши на светло-желтые прямоугольники.
-
Какова ценность this
в отмеченной линии? Зачем?
window
- отмеченная строка оценивается в начальном глобальном контексте выполнения.
if (true) {
// What is 'this' here?
}
-
Каково значение this
в отмеченной строке при выполнении obj.staticFunction()
? Зачем?
obj
- при вызове функции для объекта ThisBinding устанавливается для объекта.
var obj = {
someData: "a string"
};
function myFun() {
return this // What is 'this' here?
}
obj.staticFunction = myFun;
console.log("this is window:", obj.staticFunction() == window);
console.log("this is obj:", obj.staticFunction() == obj);
Ответ 2
Ключевое слово this
ведет себя по-разному в JavaScript по сравнению с другими языками. В объектно-ориентированных языках ключевое слово this
ссылается на текущий экземпляр класса. В JavaScript значение this
определяется в основном контекстом вызова функции (context.function()
) и местом ее вызова.
1. При использовании в глобальном контексте
Когда вы используете this
в глобальном контексте, это связано с глобальным объектом (window
в браузере)
document.write(this); //[object Window]
Когда вы используете this
внутри функции, определенной в глобальном контексте, this
все еще привязано к глобальному объекту, так как функция фактически сделана методом глобального контекста.
function f1()
{
return this;
}
document.write(f1()); //[object Window]
Выше f1
сделан метод глобального объекта. Таким образом, мы также можем вызвать его для объекта window
следующим образом:
function f()
{
return this;
}
document.write(window.f()); //[object Window]
2. При использовании внутри метода объекта
Когда вы используете this
ключевое слово внутри метода объекта, this
привязывается к "непосредственному" включающему объекту.
var obj = {
name: "obj",
f: function () {
return this + ":" + this.name;
}
};
document.write(obj.f()); //[object Object]:obj
Выше я поставил слово сразу в двойных кавычках. Следует подчеркнуть, что если вы вложите объект в другой объект, this
будет связано с непосредственным родителем.
var obj = {
name: "obj1",
nestedobj: {
name:"nestedobj",
f: function () {
return this + ":" + this.name;
}
}
}
document.write(obj.nestedobj.f()); //[object Object]:nestedobj
Даже если вы явно добавляете функцию к объекту как метод, она все равно следует приведенным выше правилам, то есть this
все еще указывает на непосредственный родительский объект.
var obj1 = {
name: "obj1",
}
function returnName() {
return this + ":" + this.name;
}
obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
3. При вызове функции без контекста
Когда вы используете this
внутреннюю функцию, которая вызывается без какого-либо контекста (то есть не для какого-либо объекта), она привязывается к глобальному объекту (window
в браузере) (даже если функция определена внутри объекта).
var context = "global";
var obj = {
context: "object",
method: function () {
function f() {
var context = "function";
return this + ":" +this.context;
};
return f(); //invoked without context
}
};
document.write(obj.method()); //[object Window]:global
Попытка все это с функциями
Мы можем попробовать вышеуказанные пункты с функциями тоже. Однако есть некоторые различия.
- Выше мы добавляли члены к объектам, используя буквенную запись объекта. Мы можем добавить членов к функциям, используя
this
. указать их. - Буквенная нотация объекта создает экземпляр объекта, который мы можем использовать немедленно. С помощью функции нам может понадобиться сначала создать ее экземпляр с помощью оператора
new
. - Также в подходе буквального объекта мы можем явно добавить членов к уже определенному объекту, используя оператор точки. Это добавляется только к конкретному экземпляру. Однако я добавил переменную в прототип функции, чтобы она отражалась во всех экземплярах функции.
Ниже я попробовал все, что мы сделали с объектом и this
выше, но от первой функции создания вместо прямого написания объекта.
/*********************************************************************
1. When you add variable to the function using this keyword, it
gets added to the function prototype, thus allowing all function
instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
this.name = "ObjDefinition";
this.getName = function(){
return this+":"+this.name;
}
}
obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition
/*********************************************************************
2. Members explicitly added to the function protorype also behave
as above: all function instances have their own copy of the
variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
return "v"+this.version; //see how this.version refers to the
//version variable added through
//prototype
}
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
3. Illustrating that the function variables added by both above
ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1
obj2.incrementVersion(); //incrementing version in obj2
//does not affect obj1 version
document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
4. 'this' keyword refers to the immediate parent object. If you
nest the object through function prototype, then 'this' inside
object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj',
getName1 : function(){
return this+":"+this.name;
}
};
document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj
/*********************************************************************
5. If the method is on an object prototype chain, 'this' refers
to the object the method was called on, as if the method was on
the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
//as its prototype
obj3.a = 999; //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
//calling obj3.fun() makes
//ProtoObj.fun() to access obj3.a as
//if fun() is defined on obj3
4. При использовании внутри функции конструктора.
Когда функция используется в качестве конструктора (то есть когда она вызывается с new
ключевым словом), this
внутреннее тело функции указывает на конструируемый новый объект.
var myname = "global context";
function SimpleFun()
{
this.myname = "simple function";
}
var obj1 = new SimpleFun(); //adds myname to obj1
//1. 'new' causes 'this' inside the SimpleFun() to point to the
// object being constructed thus adding any member
// created inside SimipleFun() using this.membername to the
// object being constructed
//2. And by default 'new' makes function to return newly
// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
5. При использовании внутри функции, определенной в цепочке прототипов
Если метод находится в цепочке прототипов объекта, this
внутри такого метода относится к объекту, к которому был вызван метод, как если бы метод был определен для объекта.
var ProtoObj = {
fun: function () {
return this.a;
}
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun()
//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3 prototype but
//'this.a' inside fun() retrieves obj3.a
6. Внутри функций call(), apply() и bind()
- Все эти методы определены в
Function.prototype
. - Эти методы позволяют написать функцию один раз и вызвать ее в другом контексте. Другими словами, они позволяют указать значение
this
которое будет использоваться во время выполнения функции. Они также принимают любые параметры, которые будут переданы исходной функции при ее вызове. -
fun.apply(obj1 [, argsArray])
Устанавливает obj1
в качестве значения this
внутри fun()
и вызывает fun()
передавая элементы argsArray
качестве аргументов. -
fun.call(obj1 [, arg1 [, arg2 [,arg3 [,...]]]])
- устанавливает obj1
в качестве значения this
внутри fun()
и вызывает fun()
передавая arg1, arg2, arg3,...
качестве своих аргументов. -
fun.bind(obj1 [, arg1 [, arg2 [,arg3 [,...]]]])
- возвращает ссылку на функцию fun
с this
внутри fun, связанным с obj1
и параметрами fun
связанными с параметрами, указанными arg1, arg2, arg3,...
- К настоящему времени разница между
apply
, call
и bind
уже стала очевидной. apply
позволяет указывать аргументы для функции как массивоподобный объект, то есть объект со свойством числовой length
и соответствующими неотрицательными целочисленными свойствами. В то время как call
позволяет указывать аргументы функции напрямую. Как apply
и call
сразу call
функцию в указанном контексте и с указанными аргументами. С другой стороны, bind
просто возвращает функцию, связанную с указанным значением this
и аргументами. Мы можем захватить ссылку на эту возвращенную функцию, присвоив ее переменной, и позже мы можем вызвать ее в любое время.
function add(inc1, inc2)
{
return this.a + inc1 + inc2;
}
var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
//above add.call(o,5,6) sets 'this' inside
//add() to 'o' and calls add() resulting:
// this.a + inc1 + inc2 =
// 'o.a' i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
// 'o.a' i.e. 4 + 5 + 6 = 15
var g = add.bind(o, 5, 6); //g: 'o.a' i.e. 4 + 5 + 6
document.write(g()+"<br />"); //15
var h = add.bind(o, 5); //h: 'o.a' i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
// 4 + 5 + 6 = 15
document.write(h() + "<br />"); //NaN
//no parameter is passed to h()
//thus inc2 inside add() is 'undefined'
//4 + 5 + undefined = NaN</code>
7. this
внутри обработчиков событий
- Когда вы назначаете функцию непосредственно обработчикам событий элемента, использование
this
непосредственно внутри функции обработки событий относится к соответствующему элементу. Такое прямое назначение функции может быть сделано с помощью метода addeventListener
или с помощью традиционных методов регистрации событий, таких как onclick
. - Аналогичным образом, когда вы используете
this
непосредственно внутри свойства события (например, <button onclick="...this..." >
) элемента, оно ссылается на элемент. - Однако использование
this
косвенно через другую функцию, вызываемую внутри обработки функции или события свойства события решает глобальный объект window
. - Такое же поведение выше достигается, когда мы присоединяем функцию к обработчику событий с помощью метода модели регистрации событий Microsoft
attachEvent
. Вместо того, чтобы назначать функцию обработчику события (и, таким образом, создавать метод функции элемента), она вызывает функцию для события (фактически вызывая ее в глобальном контексте).
Я рекомендую лучше попробовать это в JSFiddle.
<script>
function clickedMe() {
alert(this + " : " + this.tagName + " : " + this.id);
}
document.getElementById("button1").addEventListener("click", clickedMe, false);
document.getElementById("button2").onclick = clickedMe;
document.getElementById("button5").attachEvent('onclick', clickedMe);
</script>
<h3>Using 'this' "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used 'this' directly in click event property</button>
<h3>Using 'this' "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">'this' used indirectly, inside function <br /> defined & called inside event property</button><br />
<button id="button4" onclick="clickedMe()">'this' used indirectly, inside function <br /> called inside event property</button> <br />
IE only: <button id="button5">click() "attached" using attachEvent() </button>
8. this
в функции стрелки ES6
В функции стрелки this
будет вести себя как обычные переменные: оно будет унаследовано от его лексической области видимости. Функция this
, в которой определена функция стрелки, будет функцией стрелки this
.
Итак, то же поведение, что и:
(function(){}).bind(this)
Смотрите следующий код:
const globalArrowFunction = () => {
return this;
};
console.log(globalArrowFunction()); //window
const contextObject = {
method1: () => {return this},
method2: function(){
return () => {return this};
}
};
console.log(contextObject.method1()); //window
const contextLessFunction = contextObject.method1;
console.log(contextLessFunction()); //window
console.log(contextObject.method2()()) //contextObject
const innerArrowFunction = contextObject.method2();
console.log(innerArrowFunction()); //contextObject
Ответ 3
Javascript this
Простой вызов функции
Рассмотрим следующую функцию:
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
Обратите внимание, что мы запускаем это в обычном режиме, то есть строгий режим не используется.
При запуске в браузере значение this
будет записано как window
. Это потому, что window
является глобальной переменной в области видимости веб-браузера.
Если вы запустите этот же кусок кода в среде, такой как node.js, this
будет означать глобальную переменную в вашем приложении.
Теперь, если мы запустим это в строгом режиме, добавив оператор "use strict";
к началу объявления функции this
больше не будет ссылаться на глобальную переменную ни в одной из сред. Это сделано, чтобы избежать путаницы в строгом режиме. this
будет, в этом случае просто необходимо войти undefined
, потому что это то, что она есть, она не определена.
В следующих случаях мы увидим, как манипулировать значением this
.
Вызов функции на объекте
Есть разные способы сделать это. Если вы вызывали нативные методы в Javascript, такие как forEach
и slice
, вы уже должны знать, что переменная this
в этом случае относится к Object
для которого вы вызвали эту функцию (обратите внимание, что в javascript практически все является Object
, включая Array
и Function
с). Возьмите следующий код для примера.
var myObj = {key: "Obj"};
myObj.logThis = function () {
// I am a method
console.log(this);
}
myObj.logThis(); // myObj is logged
Если Object
содержит свойство, которое содержит Function
, свойство называется методом. Этот метод, при вызове, всегда будет иметь this
переменную, установленную на Object
он связан. Это верно как для строгих, так и для нестрогих режимов.
Обратите внимание, что если метод сохраняется (или, скорее, копируются) в другой переменной, ссылка на this
уже не сохраняется в новой переменной. Например:
// continuing with the previous code snippet
var myVar = myObj.thisMethod;
myVar();
// logs either of window/global/undefined based on mode of operation
Рассматривая более практичный сценарий:
var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself
new
ключевое слово
Рассмотрим функцию конструктора в Javascript:
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In 'awal.sayHello', 'this' contains the reference to the variable 'awal'
Как это работает? Хорошо, давайте посмотрим, что произойдет, когда мы используем new
ключевое слово.
- Вызов функции с
new
ключевым словом немедленно инициализирует Object
типа Person
. - Конструктор этого
Object
имеет конструктор Person
. Также обратите внимание, что typeof awal
будет возвращать только Object
. - Этому новому
Object
будет присвоен прототип Person.prototype
. Это означает, что любой метод или свойство в прототипе Person
будет доступно для всех экземпляров Person
, включая awal
. - Теперь вызывается сама функция
Person
; this
ссылка на недавно построенный объект awal
.
Довольно просто, а?
Обратите внимание, что в официальной спецификации ECMAScript нигде не говорится, что такие типы функций являются фактическими функциями constructor
. Это просто обычные функции, и new
могут быть использованы для любой функции. Просто мы используем их как таковые, и поэтому мы называем их только таковыми.
Вызов функций на Функции: call
и apply
Так что да, так как function
также являются Objects
(и фактически переменными первого класса в Javascript), даже функции имеют методы, которые... ну, сами функции.
Все функции наследуются от глобальной Function
, и два из ее многочисленных методов call
и apply
, и обе могут использоваться для манипулирования значением this
в функции, для которой они вызываются.
function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);
Это типичный пример использования call
. Он в основном принимает первый параметр и устанавливает this
в функции foo
как ссылку на thisArg
. Все остальные параметры, передаваемые для call
, передаются функции foo
качестве аргументов.
Таким образом, приведенный выше код будет регистрировать {myObj: "is cool"}, [1, 2, 3]
в консоли. Довольно хороший способ изменить значение this
в любой функции.
apply
почти то же самое, что call
accept, что он принимает только два параметра: thisArg
и массив, содержащий аргументы, которые должны быть переданы функции. Таким образом, выше call
вызов может быть переведен на apply
следующим образом:
foo.apply(thisArg, [1,2,3])
Обратите внимание, что call
и apply
могут переопределить значение this
набора с помощью вызова метода точки, который мы обсуждали во втором пункте. Достаточно просто :)
Представляя.... bind
!
bind
- брат по call
и apply
. Это также метод, унаследованный всеми функциями от глобального конструктора Function
в Javascript. Разница между bind
и call
/apply
заключается в том, что и call
и apply
фактически вызовут функцию. bind
, с другой стороны, возвращает новую функцию с thisArg
arguments
thisArg
и arguments
. Давайте возьмем пример, чтобы лучше понять это:
function foo (a, b) {
console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs 'function'
console.log (bound);
/* logs 'function () { native code }' */
bound(); // calling the function returned by '.bind'
// logs '{myObj: "even more cool now"}, [1, 2]'
Видите разницу между тремя? Это тонко, но они используются по-разному. Подобно call
и apply
, bind
также переопределит значение this
набора при вызове точечного метода.
Также обратите внимание, что ни одна из этих трех функций не изменяет исходную функцию. call
и apply
вернут значение из только что созданных функций, в то время как bind
вернет саму недавно созданную функцию, готовую к call
.
Дополнительные вещи, скопируйте это
Иногда вам не нравится тот факт, что this
меняется с областью действия, особенно с вложенной областью действия. Посмотрите на следующий пример.
var myObj = {
hello: function () {
return "world"
},
myMethod: function () {
// copy this, variable names are case-sensitive
var that = this;
// callbacks ftw \o/
foo.bar("args", function () {
// I want to call 'hello' here
this.hello(); // error
// but 'this' references to 'foo' damn!
// oh wait we have a backup \o/
that.hello(); // "world"
});
}
};
В приведенном выше коде мы видим, что значение this
изменялось с вложенной областью действия, но мы хотели получить значение this
из исходной области действия. Таким образом, мы "скопировали" this
к that
и использовали копию вместо this
. Умно, а?
Индекс:
- Что в
this
содержится по умолчанию? - Что если мы вызовем функцию как метод с нотацией Object-dot?
- Что если мы используем
new
ключевое слово? - Как мы можем манипулировать
this
с помощью call
и apply
? - Используя
bind
. - Копирование
this
чтобы решить проблемы вложенной области.
Ответ 4
"this" - все о сфере видимости. Каждая функция имеет свой собственный объем, и поскольку все в JS является объектом, даже функция может хранить некоторые значения в себе, используя "this". OOP 101 учит, что "this" применим только к экземплярам объекта. Поэтому каждый раз, когда выполняется функция, новый "экземпляр" этой функции имеет новое значение "this".
Большинство людей путают, когда они пытаются использовать "this" внутри анонимных функций закрытия, например:
(function(value) {
this.value = value;
$('.some-elements').each(function(elt){
elt.innerHTML = this.value; // uh oh!! possibly undefined
});
})(2);
Итак, внутри each(), "this" не удерживает "значение", которое вы ожидаете от него (от
this.value = value;
над ним). Итак, чтобы справиться с этой проблемой (без каламбуры), разработчик мог:
(function(value) {
var self = this; // small change
self.value = value;
$('.some-elements').each(function(elt){
elt.innerHTML = self.value; // phew!! == 2
});
})(2);
Попробуйте; вам понравится эта схема программирования
Ответ 5
this
в JavaScript всегда относится к "владельцу" функции, которая выполняется.
Если явный владелец не определен, то указывается самый верхний владелец, объект окна.
Так что если бы я сделал
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick = someKindOfFunction;
this
будет относиться к элементу объекта. Но будьте осторожны, многие люди совершают эту ошибку.
<element onclick="someKindOfFunction()">
В последнем случае вы просто ссылаетесь на функцию, а не передаете ее элементу. Следовательно, this
будет относиться к объекту окна.
Ответ 6
Поскольку этот поток натолкнулся, я собрал несколько точек для новых читателей для темы this
.
Как определяется значение this
?
Мы используем это подобно тому, как мы используем местоимения в естественных языках, таких как английский: "Джон работает быстро, потому что он пытается поймать поезд". Вместо этого мы могли бы написать "... John пытается поймать поезд".
var person = {
firstName: "Penelope",
lastName: "Barrymore",
fullName: function () {
// We use "this" just as in the sentence above:
console.log(this.firstName + " " + this.lastName);
// We could have also written:
console.log(person.firstName + " " + person.lastName);
}
}
this
не присваивается значение, пока объект не вызовет функцию, в которой он определен. В глобальной области действия все глобальные переменные и функции определены в объекте window
. Поэтому this
в глобальной функции ссылается на (и имеет значение) глобальный объект window
.
Когда use strict
, this
в глобальном и в анонимных функциях, не связанных с каким-либо объектом, имеет значение undefined
.
Ключевое слово this
наиболее неправильно понято, когда: 1) мы используем метод, который использует this
, 2), мы назначаем метод который использует this
для переменной, 3) функция, которая использует this
, передается как функция обратного вызова, а 4) this
используется внутри замыкания - внутренней функции. (2)
Что содержит будущее
Определено в ECMA Script 6, функции-стрелки принимают привязку this
от
(функция или глобальная).
function foo() {
// return an arrow function
return (a) => {
// `this` here is lexically inherited from `foo()`
console.log(this.a);
};
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!
Хотя функции-стрелки предоставляют альтернативу использованию bind()
, важно отметить, что они по существу отключают традиционный механизм this
в пользу более широкого понимания лексического охвата. (1)
Литература:
Ответ 7
Каждый контекст выполнения в javascript имеет область контекст, который задается:
- Как вызывается функция (в том числе как метод объекта, использование вызова и применения, использование нового)
- Использование привязки
- Лексически для функций стрелок (они принимают это из контекста внешнего исполнения)
Каким бы ни был этот контекст области видимости, ссылается на "this".
Вы можете изменить, что установить значение этой области , используя func.call
, func.apply
или func.bind
.
По умолчанию, и что путает большинство новичков, когда вызывающий callback вызывается после того, как событие добавлено в элемент DOM, контекст области это значение функции является элементом DOM.
jQuery делает это тривиальным для изменения с помощью jQuery.proxy.
Ответ 8
Здесь является одним из хороших источников this
в JavaScript
.
Вот резюме:
-
global this
В браузере в глобальной области this
находится объект window
<script type="text/javascript">
console.log(this === window); // true
var foo = "bar";
console.log(this.foo); // "bar"
console.log(window.foo); // "bar"
В node
с использованием repl, this
- это верхнее пространство имен. Вы можете ссылаться на него как global
.
>this
{ ArrayBuffer: [Function: ArrayBuffer],
Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
...
>global === this
true
В node
, выполняющемся из script, this
в глобальной области запускается как пустой объект. Это не то же самое, что global
\\test.js
console.log(this); \\ {}
console.log(this === global); \\ fasle
-
функция this
За исключением случаев обработчиков событий DOM или когда предоставляется thisArg
(см. ниже), как в node, так и в браузере с использованием this
в функции, которая не вызывается с помощью new
ссылок глобальный охват...
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
Если вы используете use strict;
, в этом случае this
будет undefined
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined
</script>
Если вы вызываете функцию с new
, this
будет новым контекстом, он не будет ссылаться на глобальный this
.
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
Функции, которые вы создаете, становятся объектами функции. Они автоматически получают специальное свойство prototype
, которое вы можете присвоить значениям. Когда вы создаете экземпляр, вызывая свою функцию с помощью new
, вы получаете доступ к значениям, присвоенным свойству prototype
. Вы получаете доступ к этим значениям с помощью this
.
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
Как правило, ошибочно назначать массивы или объекты на prototype
. Если вы хотите, чтобы экземпляры имели свои собственные массивы, создайте их в функции, а не прототипе.
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
Вы можете использовать this
в любой функции объекта, чтобы ссылаться на другие свойства этого объекта. Это не то же самое, что экземпляр, созданный с помощью new
.
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
В обработчике событий HTML DOM this
всегда ссылается на элемент DOM, событие было прикреплено к
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
Если вы не bind
контекст
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
Внутри атрибутов HTML, в которые вы можете поместить JavaScript, this
является ссылкой на элемент.
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
Вы можете использовать eval
для доступа к this
.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
Вы можете использовать with
, чтобы добавить this
в текущую область действия, чтобы читать и записывать значения на this
без прямого указания this
.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
jQuery во многих местах имеет this
ссылается на элемент DOM.
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>
Ответ 9
Даниэль, удивительное объяснение! Несколько слов по этому и хорошему списку указателя контекста выполнения this
в случае обработчиков событий.
В двух словах this
в JavaScript указывает объект, у которого (или из контекста выполнения) текущая функция была запущена, и она всегда доступна только для чтения, вы все равно не можете ее установить (такая попытка закончится с сообщением "Недопустимая левая сторона в присваивании".
Для обработчиков событий: обработчики событий inline, такие как <element onclick="foo">
, переопределяют любые другие обработчики, прикрепленные ранее и раньше, поэтому будьте осторожны и лучше избегайте делегирования событий внутри очереди.
И благодаря Заре Алавердян, которая вдохновила меня на этот список примеров через несогласные дебаты:)
-
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)">
Ответ 10
Вероятно, самая подробная и всеобъемлющая статья по this
вопросу:
Нежное объяснение ключевого слова "this" в JavaScript
Идея this
заключается в том, чтобы понять, что типы вызова функций имеют важное значение для установки this
значения.
Когда возникают проблемы с this
, не спрашивайте себя:
Откуда this
взято?
но спросите себя:
Как вызывается функция?
Для функции стрелки (специальный случай прозрачности контекста) спросите себя:
Какое значение имеет this
значение, когда определена функция стрелки?
Это мышление правильное, когда вы имеете дело с this
и избавит вас от головной боли.
Ответ 11
Существует много путаницы в отношении того, как "this" ключевое слово интерпретируется в JavaScript. Надеюсь, эта статья заложит все, чтобы отдохнуть раз и навсегда. И многое другое. Пожалуйста, внимательно прочитайте всю статью. Будьте предупреждены, что эта статья длинная.
Независимо от контекста, в котором он используется, "this" всегда ссылается на текущий "текущий объект в Javascript. Однако то, что " текущий объект" отличается в соответствии с контекстом. Контекст может быть в точности 1 из 6 следующим образом:
- Глобальный (т.е. вне всех функций)
- Внутри прямой "Non Bound Function" Call (т.е. функция с не была связана вызовом functionName.bind)
- Внутри косвенной "Не привязанной функции" Вызов через functionName.call и functionName.apply
- Внутри функции "Связанная функция" (т.е. функция была связана, вызывая functionName.bind)
- Пока создание объекта через "новый"
- Внутренний обработчик событий Inline DOM
Ниже описывается каждый из этих контекстов один за другим:
-
Глобальный контекст (т.е. вне всех функций):
Вне всех функций (т.е. в глобальном контексте) "current
объект (и, следовательно, значение "this") всегда
"окно" для браузеров.
-
Внутри прямой "Не привязанная функция" Вызов:
Внутри прямой "Non Bound Function" Call, объект, который
вызываемый вызов функции становится "текущим объектом" (и, следовательно,
значение "this"). Если функция вызывается без явного текущего объекта, текущий объект является либо "окном (для не строгого режима), либо undefined (для строгого режима). Любая функция (или переменная), определенная в
Глобальный контекст автоматически становится свойством объекта "окна. Например, предположим, что функция определена в глобальном контексте как
function UserDefinedFunction(){
alert(this)
}
он становится свойством объекта window, как если бы вы определили
это как
window.UserDefinedFunction=function(){
alert(this)
}
В режиме "Не строгого режима" вызов/вызов этой функции непосредственно через "UserDefinedFunction()" будет автоматически вызывать/вызывать
он как "window.UserDefinedFunction()" делает "окно" как
"текущий объект" (и, следовательно, значение "this") в пределах "UserDefinedFunction" . Включение этой функции в "Non Strict Mode" будет приведет к следующему
UserDefinedFunction() // displays [object Window] as it automatically gets invoked as window.UserDefinedFunction()
В "Строгий режим", вызов/вызов функции непосредственно через
"UserDefinedFunction()" будет "NOT" автоматически вызывать/вызывать его как "window.UserDefinedFunction()" .Сохранить текущий
объект " (и значение "this") в пределах
"UserDefinedFunction" должен быть undefined. Вызов этой функции в "Строгий режим" приведет к следующему
UserDefinedFunction() // displays undefined
Однако, ссылаясь на явное использование окна-объекта,
следующие
window.UserDefinedFunction() // "always displays [object Window] irrespective of mode."
Посмотрим на другой пример. Посмотрите следующий код
function UserDefinedFunction()
{
alert(this.a + "," + this.b + "," + this.c + "," + this.d)
}
var o1={
a:1,
b:2,
f:UserDefinedFunction
}
var o2={
c:3,
d:4,
f:UserDefinedFunction
}
o1.f() // Shall display 1,2,undefined,undefined
o2.f() // Shall display undefined,undefined,3,4
В приведенном выше примере мы видим, что когда "UserDefinedFunction"
вызывается с помощью o1, "this" принимает значение o1, а
значение его свойств "a" и "b" . Значение
"c" и "d" были показаны как undefined как o1.
не определять эти свойства
Аналогично, когда "UserDefinedFunction" вызывается через o2
"this" принимает значение o2, а значение его свойств "c" и "d" отображается Значение "a" и "b" было показано как undefined, поскольку o2 не определяет эти свойства.
-
Внутри косвенной "Не привязанной функции" Вызов через functionName.callи functionName.apply:
Когда "Non Bound Function" вызывается через
functionName.call или functionName.apply, "текущий объект (и, следовательно, значение "this") устанавливается на значение
"this" (первый параметр) передается call/apply. Следующий код демонстрирует то же самое.
function UserDefinedFunction()
{
alert(this.a + "," + this.b + "," + this.c + "," + this.d)
}
var o1={
a:1,
b:2,
f:UserDefinedFunction
}
var o2={
c:3,
d:4,
f:UserDefinedFunction
}
UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined
UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined
UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4
UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4
o1.f.call(o2) // Shall display undefined,undefined,3,4
o1.f.apply(o2) // Shall display undefined,undefined,3,4
o2.f.call(o1) // Shall display 1,2,undefined,undefined
o2.f.apply(o1) // Shall display 1,2,undefined,undefined
В приведенном выше коде ясно, что значение "this" для любого "NON
Связанная функция "может быть изменена с помощью вызова/применения. Кроме того, если
"this" не передается явно в вызов/применение, "текущий объект (и, следовательно, значение "this") установлен в "окно" в нестрочном режиме и "undefined" в строгом режиме.
-
Внутри функции "Связанная функция" (т.е. функция, связанная вызовом functionName.bind):
Связанная функция - это функция, значение которой "this"
исправлено. Следующий код показал, как работает "this" в случае
связанной функции
function UserDefinedFunction()
{
alert(this.a + "," + this.b + "," + this.c + "," + this.d)
}
var o1={
a:1,
b:2,
f:UserDefinedFunction,
bf:null
}
var o2={
c:3,
d:4,
f:UserDefinedFunction,
bf:null
}
var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1
bound1() // Shall display 1,2,undefined,undefined
var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2
bound2() // Shall display undefined,undefined,3,4
var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2
bound3() // Shall display undefined,undefined,3,4
var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1
bound4() // Shall display 1,2,undefined,undefined
o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2
o1.bf() // Shall display undefined,undefined,3,4
o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1
o2.bf() // Shall display 1,2,undefined,undefined
bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
Как указано в приведенном выше коде, значение "this" для любой "Связанной функции"
НЕ МОЖЕТ быть изменен с помощью вызова/применения. Кроме того, если "this"
параметр явно не передан для привязки, "текущий объект"
(и, следовательно, значение "this") установлено в "окно" в Non
строгий режим и "undefined" в строгом режиме. Еще кое-что.
Привязка уже связанной функции не изменяет значение "this".
Он остается установленным как значение, заданное первой функцией связывания.
-
Пока создание объекта через "новый" :
Внутри функции-конструктора "текущий объект (и, следовательно, значение
"this") ссылается на объект, который в настоящее время создается
через "новый" , независимо от статуса привязки функции. Однако
если конструктор является связанной функцией, он должен быть вызван с
предопределенный набор аргументов, заданных для связанной функции.
-
Внутренний обработчик событий Inline DOM:
Посмотрите на следующий фрагмент HTML
<button onclick='this.style.color=white'>Hello World</button>
<div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>
"this" в приведенных выше примерах относится к элементу "button", а
"div" соответственно.
В первом примере цвет шрифта кнопки должен быть установлен на
белый при нажатии.
Во втором примере, когда щелкнут элемент "div" , он должен
вызовите функцию OnDivClick со своим вторым параметром
ссылаясь на элемент с щелчком div. Однако значение "this"
в OnDivClick НЕ ДОЛЖЕН ссылаться на нажатый div
элемент. Он должен быть установлен как "оконный объект или
"undefined" в Нестандартных и Строгих моделях соответственно (если OnDivClick является несвязанной функцией) или установите для предопределенного
Связанное значение (если OnDivClick является связанной функцией)
Ниже приведена вся статья
-
В глобальном контексте "this" всегда ссылается на "окно
-
Всякий раз, когда вызывается функция, она вызывается в контексте
object ("текущий объект). Если текущий объект явно не указан,
текущий объект - это "оконный объект в NON Strict
Mode и "undefined" в строгом режиме по умолчанию.
-
Значение "this" внутри функции Non Bound является ссылкой на объект, в контексте которого вызывается функция ("текущий объект" ).
-
Значение "this" внутри функции Non Bound может быть переопределено
вызов и применить методы функции.
-
Значение "this" фиксировано для функции Bound и не может быть
переопределить вызов и применить методы функции.
-
Связывание и уже связанная функция не изменяет значение "this". Он остается установленным как значение, заданное первой функцией связывания.
-
Значение "this" внутри конструктора - это объект, который
создано и инициализировано
-
Значение "this" внутри встроенного обработчика событий DOM является ссылкой
к элементу, для которого задан обработчик события.
Ответ 12
Это лучшее объяснение, которое я видел: понять JavaScripts это с Clarity
Эта ссылка ВСЕГДА ссылается (и содержит значение) на объект - единственный объект - и обычно используется внутри функции или метода, хотя может использоваться вне функции в глобальной области видимости. Обратите внимание, что когда мы используем строгий режим, он содержит значение undefined в глобальных функциях и в анонимных функциях, которые не связаны ни с одним объектом.
Существует четыре сценария, в которых это может сбить с толку:
- Когда мы передаем метод (который использует это) в качестве аргумента для использования в качестве функции обратного вызова.
- Когда мы используем внутреннюю функцию (замыкание). Важно отметить, что замыкания не могут получить доступ к внешним функциям этой переменной с помощью ключевого слова this, поскольку переменная this доступна только самой функции, а не внутренним функциям.
- Когда метод, основанный на этом, назначается переменной в разных контекстах, в этом случае он ссылается на другой объект, чем первоначально предполагалось.
- При использовании этого вместе с привязкой, применением и вызовом методов.
Он приводит примеры кода, объяснения и решения, которые, на мой взгляд, были очень полезны.
Ответ 13
Трудно получить хорошее представление о JS или написать больше, чем что-либо тривиальное в нем, если вы не понимаете его полностью. Вы не можете просто позволить себе быстро окунуться :) Я думаю, что лучший способ начать работу с JS - сначала посмотреть эти видео-лекции Дугласа Крокфорда - http://yuiblog.com/crockford/, который охватывает это и то, и все остальное о JS.
Ответ 14
В псевдоклассических терминах многие лекции обучают ключевому слову 'this' как объект, созданный конструктором класса или объекта. Каждый раз, когда новый объект создается из класса, представьте, что под капотом создается и возвращается локальный экземпляр объекта 'this'. Я помню, как он учил так:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
Ответ 15
this
- одна из неправильно понятых концепций в JavaScript, потому что она ведет себя немного иначе, чем место. Просто this
относится к "владельцу" функции, которую мы сейчас выполняем.
this
помогает получить текущий объект (контекст выполнения a.k.a.), с которым мы работаем. Если вы понимаете, в каком объекте выполняется текущая функция, вы можете легко понять, что текущий this
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
Выше мы создаем 3 переменные с одинаковым именем "val". Один в глобальном контексте, один внутри obj и другой внутри innerMethod obj. JavaScript разрешает идентификаторы в определенном контексте, поднимая цепочку областей действия из локального глобального.
Несколько мест, где this
можно дифференцировать
Вызов метода объекта
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Когда выполняется строка1, JavaScript устанавливает контекст выполнения (EC) для вызова функции, устанавливая this
объекту , на который ссылается все, что было до последнего ".. поэтому в последней строке вы можете понять, что a()
был выполнен в глобальном контексте, который является window
.
С конструктором
this
может использоваться для ссылки на создаваемый объект
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
Когда выполняется новый Person()
, создается совершенно новый объект. Person
вызывается, а его this
устанавливается для ссылки на этот новый объект.
Вызов функции
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
Если мы пропустим ключевое слово new
, whatIsThis
ссылается на самый глобальный контекст, он может найти (window
)
С обработчиками событий
Если обработчик события inline, this
относится к глобальному объекту
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id='thebutton' onclick='click_handler()'>Click me!</button>
При добавлении обработчика событий через JavaScript this
относится к элементу DOM, который сгенерировал событие.
Ответ 16
Значение "this" зависит от "контекста", в котором выполняется функция. Контекстом может быть любой объект или глобальный объект, т.е. Окно.
Таким образом, семантика "this" отличается от традиционных языков ООП. И это вызывает проблемы:
1. когда функция передается другой переменной (скорее всего, обратный вызов); и 2. когда замыкание вызывается из метода-члена класса.
В обоих случаях это устанавливается как окно.
Ответ 17
Может ли this помочь? (Большая часть путаницы 'this' в javascript исходит из того факта, что она вообще не связана с вашим объектом, а с текущей исполняемой областью - это может быть не совсем так, как это работает, но мне всегда кажется, см. статью для полного объяснения)
Ответ 18
Немного информации об этом ключевом слове
Позвольте записывать this
ключевое слово в консоль в глобальной области без какого-либо кода, но
console.log(this)
В Client/Browser this
ключевое слово - глобальный объект, который является window
console.log(this === window) // true
а также
В среде выполнения Server/Node/Javascript this
ключевое слово также является глобальным объектом, который является module.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
Имейте в виду, что exports
- это просто ссылка на module.exports
Ответ 19
это использование для области видимости как это
<script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>
значение txt1 и txt равно
В приведенном выше примере
$ (this) = $('# tbleName tbody tr') - это тот же
Ответ 20
У меня есть другое мнение об this
из других ответов, которые, я надеюсь, будут полезны.
Один из способов взглянуть на JavaScript - это увидеть только 1 способ вызова функции 1. это
functionObject.call(objectForThis, arg0, arg1, arg2, ...);
Для objectForThis
всегда objectForThis
какое-то значение.
Все остальное является синтаксическим сахаром для functionObject.call
Итак, все остальное можно описать тем, как оно переводится в functionObject.call
.
Если вы просто вызываете функцию, то this
"глобальный объект", который в браузере является окном
function foo() {
console.log(this);
}
foo(); // this is the window object
Ответ 21
Резюме this
Javascript:
- Значение
this
определяется тем, как функция вызывается не, где она была создана! - Обычно значение
this
определяется Объектом, который остается от точки. (window
в глобальном пространстве) - В обработчиках событий значение
this
относится к элементу DOM, на котором было названо событие. - Когда функция вызывается с ключевым словом
new
значение this
относится к вновь созданному объекту - Вы можете манипулировать значением
this
с помощью функций: call
, apply
, bind
Пример:
let object = {
prop1: function () {console.log(this);}
}
object.prop1(); // object is left of the dot, thus this is object
const myFunction = object.prop1 // We store the function in the variable myFunction
myFunction(); // Here we are in the global space
// myFunction is a property on the global object
// Therefore it logs the window object
Ответ 22
Что такое ключевое слово "this" в JavaScript
Это ключевое слово относится к объекту, тому объекту, который выполняет текущий бит кода JavaScript.
Другими словами, каждая функция javascript во время выполнения имеет ссылку на свой текущий контекст выполнения, называемый this. Контекст выполнения означает, что здесь так называется функция.
Чтобы понять это ключевое слово, нам нужно только знать, как, когда и откуда вызывается функция, не имеет значения, как и где функция объявлена или определена.
function bike() {
console.log(this.name);
}
var name = "Ninja";
var obj1 = { name: "Pulsar", bike: bike };
var obj2 = { name: "Gixxer", bike: bike };
bike(); // "Ninja"
obj1.bike(); // "Pulsar"
obj2.bike(); // "Gixxer"
В приведенном выше фрагменте кода функция job bike()
печатает this.name
что означает попытку печати свойства name текущего контекста выполнения (iethis object)
.
В приведенном выше фрагменте кода, когда вызывается функция bike()
она печатает "Ninja", поскольку контекст выполнения не указан, поэтому по умолчанию его глобальный контекст и имя переменной присутствуют в глобальном контексте, значение которого равно "Ninja".
В случае вызова obj1().bike()
печатается "Pulsar", и причина этого заключается в том, что функция bike()
вызывается с контекстом выполнения как obj1
поэтому this.name
становится obj1.name
. То же самое с obj2.bike()
где контекст выполнения функции bike()
- obj2
.
По умолчанию и неявное связывание "это"
Если мы находимся в строгом режиме, то значение этого ключевого слова по умолчанию не определено, в противном случае это ключевое слово действует как глобальный объект, так называемое связывание этого ключевого слова по умолчанию. (по умолчанию это оконный объект в случае браузера).
когда есть свойство объекта, которое мы вызываем как метод, тогда этот объект становится этим объектом или объектом контекста выполнения для этого метода, это неявное связывание этого ключевого слова.
var obj1 = {
name: "Pulsar",
bike: function() {
console.log(this.name);
}
}
var obj2 = { name: "Gixxer", bike: obj1.bike };
var name = "Ninja";
var bike = obj1.bike;
bike(); // "Ninja"
obj1.bike(); // "Pulsar"
obj2.bike(); // "Gixxer"
В приведенном выше фрагменте кода вызов функции bike()
является примером привязки по умолчанию. obj1.bike()
и obj2.bike()
являются примерами неявного связывания. Здесь велосипедная функция объявляется как часть obj1
но независимо от того, когда мы executeobj2.bike()
, контекст выполнения имеет вид obj2
поэтому obj2.name
.
Важно знать, как, когда и откуда вызывается функция, не имеет значения, где объявлена функция.
Явное и фиксированное связывание ключевого слова this
Если мы используем метод call и apply с вызывающей функцией, оба эти метода принимают в качестве первого параметра в качестве контекста выполнения. это то, что связывает.
function bike() {
console.log(this.name);
}
var name = "Ninja";
var obj = { name: "Pulsar" }
bike(); // "Ninja"
bike.call(obj); // "Pulsar"
В этом фрагменте выше, если мы вызываем функцию bike с методом call()
передавая объект контекста выполнения obj в качестве первого аргумента, тогда obj присваивается этому объекту и печатает "Pulsar", который является ничем иным, как obj.name
. Это называется явной привязкой этого ключевого слова.
В фиксированной или жесткой привязке
мы можем заставить этот объект всегда быть одинаковым независимо от того, откуда и как он вызывается.
var bike = function() {
console.log(this.name);
}
var name = "Ninja";
var obj1 = { name: "Pulsar" };
var obj2 = { name: "Gixxer" };
var originalBikeFun = bike;
bike = function() {
originalBikeFun.call(obj1);
};
bike(); // "Pulsar"
bike.call(obj2); // "Pulsar"
В соответствии с приведенным выше фрагментом кода, bike()
и bike.call(obj2)
вызывают вызов "Pulsar", который является ничем иным, как obj1.name
означает, что контекст выполнения функции bike всегда obj1
и это происходит из-за originalBikeFun.call(obj1)
; Такого рода эта привязка является просто еще одним вариантом явного связывания, называемого фиксированным связыванием.
Ответ 23
this
ключевое слово относится к его текущему окружению
Ответ 24
Простой ответ:
Это ключевое слово всегда зависит от контекста вызова. Они упомянуты ниже.
-
ФУНКЦИЯ ВЫЗЫВАЕТСЯ С НОВЫМ КЛЮЧОМ
Если функция вызывается с ключевым словом NEW, тогда THIS будет привязан к вновь созданному объекту.
function Car(){
this.name="BMW";
}
const myCar=new Car();
myCar.name; // output "BMW"
В приведенном выше примере это будет связано с объектом 'myCar'
-
ФУНКЦИЯ ВЫЗЫВАЕТСЯ ТОЛЬКО С ИСПОЛЬЗОВАНИЕМ МЕТОДОВ ВЫЗОВА И ПРИМЕНЕНИЯ.
В этом случае ЭТО будет связано с объектом, который явно передается функции.
var obj1={"name":"bond"};
function printMessage(msg){
return msg+" "+this.name;
}
const message=printMessage.call(obj1,"my name is ");
console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.
-
ЕСЛИ ФУНКЦИЯ ВЫЗЫВАЕТСЯ С ОБЪЕКТОМ, НЕПРАВИЛЬНО, ТОГДА ЭТО БУДЕТ СВЯЗАНО С ЭТИМ ОБЪЕКТОМ
var obj1={
"name":"bond",
getName: function () {
return this.name;
}
};
const newname=obj1.getName();
console.log(newname); //HERE THIS WILL BE BOUND TO obj1(WHITCHEVER OBJECT IS MENTIONED BEFORE THE DOT THIS WILL BE BOUND TO THAT)
-
КОГДА ФУНКЦИЯ ВЫЗЫВАЕТСЯ БЕЗ ЛЮБОГО КОНТЕКСТА, ЭТО БУДЕТ СВЯЗАНО С ГЛОБАЛЬНЫМ ОБЪЕКТОМ
const util = {
name: 'Utility',
getName: function () {
return this.name;
};
const getName=util.getName;
const newName=getName();
console.log(newName); // IF THIS EXECUTED IN BROWSER THIS WILL BE BOUND TO WINDOW OBJECT. IF THIS EXECUTED IN SERVER THIS WILL BE BOUND TO GLOBAL OBJECT
-
В строгом режиме это будет не определено
function setName(name){
"use strict"
return this.name;
}
setName(); //WILL BE ERROR SAYING name IS UNDEFINED.
Ответ 25
"this" - все о сфере видимости. Каждая функция имеет свой собственный объем, и поскольку все в JS является объектом, даже функция может хранить некоторые значения в себе с помощью "this".
$('#a').click(function(){
console.log($(this).attr('href'));
});