Как работает ключевое слово" this"?
Я заметил, что, похоже, нет четкого объяснения того, что this
ключевое слово и как оно правильно (и неправильно) используется в JavaScript на сайте переполнения стека.
Я был свидетелем очень странного поведения с ним и не смог понять, почему это произошло.
Как this
работа и когда ее следует использовать?
20 ответов
рекомендую почитать Майк Уэстс область в JavaScript (зеркала) в первую очередь. Это отличное, дружественное введение в понятия this
и цепочки областей в JavaScript.
как только вы начнете привыкать к this
правила очень просты. The Стандарт 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
...по прямому вызову
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()
. См.chuckj это to (1, eval) ('this') vs eval ('this') в JavaScript? и подробно ECMA-262-5 Дмитрия Сошникова. Глава 2. строгий режим. для того, когда вы можете использовать косвенный eval()
звонок.
ввод кода функции
это происходит при вызове функции. Если функция вызывается на объекте, например в obj.myMethod()
или эквивалент obj["myMethod"]()
, затем ThisBinding устанавливается на объект (obj
в Примере; §13.2.1). В большинстве других случаев, ThisBinding устанавливается в глобальный объект (§10.4.3).
причина написания "в большинстве других случаев" заключается в том, что есть восемь встроенных функций ECMAScript 5, которые позволяют указывать это в списке аргументов. Эти специальные функции принимают так называемый 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 делают это, потому что он, как правило, поддерживает большинство общие случаи использования, и пользователи библиотеки обычно считают это поведение более удобным. При передаче функций обратного вызова referencing 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);
просто для удовольствия, Проверьте свое понимание с некоторыми примерами
чтобы показать ответы, наведите курсор мыши на светло-желтые коробки.
-
каково значение
this
по отмеченной линии? Почему?window
- отмеченная строка оценивается в начальном глобальном контексте выполнения.if (true) { // What is `this` here? }
-
каково значение
this
at отмеченная строка, когда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);
-
каково значение
this
по отмеченной линии? Почему?window
в этом примере интерпретатор JavaScript вводит код функции, но потому что
myFun
/obj.myMethod
не вызывается для объекта, ThisBinding имеет значениеwindow
.это отличается от Python, в котором доступ к методу (
obj.myMethod
) создает объект связанного метода.var obj = { myMethod: function () { return this; // What is `this` here? } }; var myFun = obj.myMethod; console.log("this is window:", myFun() == window); console.log("this is obj:", myFun() == obj);
-
каково значение
this
по отмеченной линии? Почему?window
это было сложно. При оценке кода eval
this
иobj
. Однако в коде evalmyFun
is не вызывается объект, поэтому ThisBinding имеет значениеwindow
для вызова.function myFun() { return this; // What is `this` here? } var obj = { myMethod: function () { eval("myFun()"); } };
-
каково значение
this
по отмеченной линии? Почему?obj
строку
myFun.call(obj);
вызывает специальную встроенную функциюFunction.prototype.call()
, который принимаетthisArg
в качестве первого аргумента.function myFun() { return this; // What is `this` here? } var obj = { someData: "a string" }; console.log("this is window:", myFun.call(obj) == window); console.log("this is obj:", myFun.call(obj) == obj);
на 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
является методом глобального объекта. Таким образом, мы также можем вызвать его на и call
немедленно вызывает функцию в указанном контексте и с указанными аргументами. С другой стороны,--56--> просто возвращает функцию, привязанную к указанному 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..." >
) элемента, он относится к элементу.
использование - то же самое выше поведение достигается при присоединении функции к обработчику событий с помощью метода модели регистрации событий
attachEvent
. Вместо того, чтобы назначать функцию обработчику событий (и, таким образом, делать метод функции элемента), он вызывает функцию на событии (эффективно вызывая его в глобальном контексте).
this
косвенно через другую функцию, вызываемую внутри функции обработки событий или свойства события, разрешает глобальный объект window
.
рекомендую лучше попробовать это в 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>
в JavaScript!--9-->
простой вызов функции
рассмотрим следующую функцию:
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
обратите внимание, что мы работает в обычном режиме, т. е. строгий режим не используется.
при запуске в браузере, стоимостью this
будет зарегистрирован как window
. Это потому что window
является глобальной переменной в области веб-браузера.
если вы запустите этот же фрагмент кода в такой среде, как узел.js,this
будет ссылаться на глобальную переменную в вашем приложении.
теперь, если мы запустим это в строгом режиме, добавив оператор "use strict";
к началу объявления функции,this
больше не будет ссылаться на глобальную переменную ни в одном из окрестностей. Это делается во избежание путаницы в строгом режиме. this
будет, в этом случае просто log undefined
, потому что это не определено.
в следующих случаях мы увидим, как чтобы манипулировать значением this
.
вызов функции на объекте
есть разные способы сделать это. Если вы вызвали собственные методы в Javascript, такие как forEach
и slice
, вы уже должны знать, что this
переменная в этом случае относится к Object
на котором вы вызвали эту функцию (обратите внимание, что в javascript почти все является Object
, включая Array
s и Function
s). Возьмите следующий код для образец.
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
будет назначена protoype изPerson.prototype
. Это означает, что любой метод или свойство вPerson
прототип будет доступен для всех экземпляровPerson
, включаяawal
. - функции
Person
сам теперь вызывается;this
быть ссылкой на недавно построенный объектawal
.
довольно straighforward, а?
обратите внимание, что официальная спецификация ECMAScript не указывает, что такие типы функций являются актуальными constructor
функции. Это просто нормальные функции, и new
можно использовать в любой функции. Просто мы используем их как таковые и называем только таковыми.
вызов функций на функции : call
и apply
так что да, начиная с function
s также Objects
(и фактически переменные первого класса в Javascript), даже функции имеют методы, которые есть... ну, функции themselved.
все функции наследуются от глобальных 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
в качестве аргументов.
Таким образом, приведенный выше код будет log {myObj: "is cool"}, [1, 2, 3]
в консоли. Довольно хороший способ изменить значение this
в любую функцию.
apply
почти то же самое, что call
примите что оно принимает только 2 параметра:thisArg
и массив, содержащий аргументы для передачи функции. Итак, выше call
вызов можно перевести на apply
такой:
foo.apply(thisArg, [1,2,3])
обратите внимание, что call
и apply
можно переопределить значение this
set by dot method invocation мы обсудили во втором пуле.
Достаточно просто :)
представления.... bind
!
bind
является братом call
и apply
. Это также метод, унаследованный всеми функциями от global Function
конструктор в Javascript. Разница между bind
и call
/apply
заключается в том, что обе call
и apply
фактически вызовет функцию. bind
, с другой стороны, возвращает новую функцию с thisArg
и arguments
pre-set. Давайте возьмем пример, чтобы лучше понять это:
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
установить с помощью вызова dot-метода.
Также отметим, что ни одна из этих трех функций внесите изменения в исходную функцию. call
и apply
вернет значение из недавно построенных функций, в то время как bind
вернет только что построенную функцию, готовую к вызову.
дополнительные материалы, скопируйте это
иногда, вам не нравится тот факт, что 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
to that
и использовал копию вместо this
. Умно, да?
"это" - это все о области. Каждая функция имеет свою собственную область, и поскольку все в JS является объектом, даже функция может хранить некоторые значения в себе, используя "это". ООП 101 учит, что "это" применимо только к экземпляров объекта. Поэтому каждый раз, когда функция выполняется, новый " экземпляр "этой функции имеет новое значение"это".
большинство людей путаются, когда они пытаются использовать "это" внутри анонимной функции закрытия например:
(function(value) { this.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = this.value; // uh oh!! possibly undefined }); })(2);
Итак, здесь, внутри каждого (), "это" не содержит "значение", которое вы ожидаете (от
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);
попробуйте; вам начнет нравиться этот шаблон программирования
this
в Javascript всегда ссылается на "владельца" функции, которая является выполняется.
если явный владелец не определен,то ссылается самый верхний владелец, объект window.
так если бы я сделал
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick = someKindOfFunction;
this
будет ссылаться на объект элемента. Но будьте осторожны, многие люди делают эту ошибку
<element onclick="someKindOfFunction()">
в последнем случае вы просто ссылаетесь на функция, а не передать его элементу. Поэтому this
будет ссылаться на объект window.
поскольку эта тема столкнулась, я собрал несколько очков для читателей, новых для this
темы.
как значение this
определить?
мы используем это подобно тому, как мы используем местоимения в естественных языках, таких как английский: "Джон работает быстро, потому что он пытается успеть на поезд."Вместо этого мы могли бы написать "... Джон пытается успеть на поезд".
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
не присваивается значение пока объект не вызовет функцию, в которой она определена. В глобальной области все глобальные переменные и функции определяются на
- как вызывается функция (в том числе в качестве метода объекта, использование вызов и применить, использование новая)
- использование bind
- лексически для функций стрелки (они принимают этой of их внешний контекст исполнения)
независимо от того, что контекст области, ссылается на "это".
вы можете изменить установите значение этой область контекст используя func.call
, func.apply
или func.bind
.
по умолчанию, и что смущает большинство новичков, когда обратный звонок прослушиватель вызывается после того, как событие вызывается на элементе DOM,областью этой значение функции является элементом DOM.
jQuery делает это тривиальным для изменения с помощью jQuery.полномочие.
здесь один хороший источник this
на JavaScript
.
Итак:
-
глобальные этот
в браузере, в глобальной области,
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
выполнение скриптаthis
в глобальной области начинается как пустой объект. Это не то же самое какglobal
\test.js console.log(this); \ {} console.log(this === global); \ fasle
этой
за исключением случая обработчиков событий DOM или когда thisArg
(см. Дальше), как в узле, так и в браузере, используя 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
the 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"
- DOM событие это
в обработчике событий 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 это
внутри атрибутов 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 это
можно использовать 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 это
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>
Даниэль, удивительное объяснение! Пара слов на этом и хороший список this
указатель контекста выполнения в случае обработчиков событий.
в двух словах this
в JavaScript указывает объект, из которого (или из контекста выполнения) была запущена текущая функция, и он всегда доступен только для чтения, вы не можете установить его в любом случае (такая попытка закончится сообщением "недопустимая левая сторона в назначении".
для обработчиков событий: встроенные события обработчики, такие как <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)">
есть много путаницы относительно того, как "этот" ключевое слово интерпретируется в JavaScript. Надеюсь, эта статья положит все это на покой раз и навсегда. И многое другое. Пожалуйста, внимательно прочитайте всю статью. Предупреждаю, что эта статья длинная.
независимо от контекста, в котором оно используется, "этот" всегда ссылается на "текущий объект" в Javascript. Однако, что за "текущий объект" отличается по контекст. The контекст может быть именно 1 из 6 следующее:
- глобальные (т. е. вне всех функций)
- Внутри Прямой" Не Связанной Функции " Вызов (т. е. функция, которая имеет не было связывается по телефону functionName.bind)
- Внутри Косвенной " Non Связанной Функции" Звоните через functionName.звоните и functionName.применить
- Внутри" Связанной Функции " Вызов (т. е. функция привязан по телефону functionName.bind)
- при создании объекта через "new"
- внутри встроенного обработчика событий DOM
в ниже описывается каждый из этих контекстов один за другим:
-
Глобальный Контекст (т. е. вне всех функций):
вне всех функций (т. е. в глобальном контексте) в "текущий объект" (и, следовательно, стоимость "этот") всегда окно""окно""
вероятно, самая подробная и исчерпывающая статья о this
следующий:
нежное объяснение ключевого слова "this" в JavaScript
идея this
должен понимать, что типы вызовов функций имеют важное значение для настройки this
значение.
при возникновении проблем с идентификацией this
, не задайте себе вопрос:
где
this
принято от?
но do задайте себе вопрос:
как функция вызывается?
для функции стрелки (особый случай прозрачности контекста) спросите себя:
какое значение имеет
this
где функция стрелка определена?
это мышление правильно при работе с this
и спасет вас от головная боль.
Это лучшее объяснение, которое я видел. Понять JavaScripts этой ясность
на этой ссылка всегда ссылается на (и содержит значение) объект-единичный объект, и он обычно используется внутри функции или метод, хотя его можно использовать вне функции в глобальном масштаб. Обратите внимание, что когда мы используем строгий режим, это имеет значение undefined в глобальных функциях и анонимных функциях что не привязан к любому объекту.
есть четыре условия, где этой можно запутаться:
- когда мы передаем метод (который использует этой) в качестве параметра используется в качестве функции обратного вызова.
- другой случай, когда это неправильно понято, - это когда мы используем внутренний метод (закрытие). Важно отметить, что закрытие не может получить доступ к внешней функции этой переменной с помощью это ключевое слово, потому что эта переменная доступна только самой функцией, а не внутренними функциями.
- используя этой когда метод присваивается переменной. The этой значение привязано к другому объекту, если мы назначаем метод, который использует это переменной
- используя этой при использовании методов bind, apply и call.
Он дает примеры кода, объяснения и исправления кода, которые я думал, были очень полезно.
трудно получить хорошее представление о JS или написать больше, чем что-либо тривиальное в нем, если вы не понимаете его полностью. Вы не можете просто позволить себе быстро окунуться :) я думаю, что лучший способ начать работу с JS-это сначала посмотреть эти видеолекции Дугласа Крокфорда -http://yuiblog.com/crockford/, который охватывает это и то, и все остальное о JS.
в псевдоклассических терминах способ, которым многие лекции учат ключевое слово "this", является объектом, созданным классом или конструктором объектов. Каждый раз, когда новый объект создается из класса, представьте, что под капотом создается и возвращается локальный экземпляр объекта "this". Помню, он учил так:--2-->
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;
this
является одной из неправильно понятых концепций в JavaScript, потому что она ведет себя немного по-разному от места к месту. Просто this
относится к "владелец" функции, которую мы в настоящее время выполняем.
this
помогает получить текущий объект (a.к. a. контекст выполнения) мы работаем. Если вы понимаете, в каком объекте выполняется текущая функция, вы можете легко понять, что current this
is
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 переменные с тем же именем "вал". Один в глобальном контексте, один внутри 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
когда выполняется line1, 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
)
с обработчиками событий
если обработчик событий рядный, 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, который сгенерировал событие.
- вы также можете управлять контексте используя
.apply()
.call()
и.bind()
- jQuery proxy-это еще один способ, который вы можете использовать, чтобы убедиться, что это в функции будет желаемым значением. (Проверка понимание $.proxy (), с помощью jQuery.использование прокси ())
- что значит
var that = this
означает в JavaScript
значение "this" зависит от" контекста", в котором выполняется функция. Контекст может быть любой объект или глобальный объект, т. е. окно.
таким образом, семантика " это " отличается от традиционных языков ООП. И это вызывает проблемы: 1. когда функция передается другой переменной (скорее всего, обратный вызов); и 2. при закрытии вызывается из метода-члена класса.
в обоих случаях установлено значение window.
Whould этой помочь? (Большая путаница "этого" в javascript исходит из того, что он обычно не связан с вашим объектом, но с текущей областью выполнения-это может быть не совсем так, как это работает, но всегда кажется мне таким-см. статью для полного объяснения)
немного информации о этой ключевое слово
давайтеthis
ключевое слово для консоли в глобальной области без какого-либо кода, но
console.log(this)
на Клиент/Браузер this
ключевое слово является глобальным объектом, который является window
console.log(this === window) // true
и
на сервер/узел / Javascript runtime this
ключевое слово также является глобальным объектом, который является module.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
имейте в виду exports
это просто ссылка module.exports
это использование для области так же, как это
<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') то же самое
резюме this
Javascript:
- значение
this
определяется как функция вызывается не, где она была создана! - обычно значение
this
определяется объектом, который находится слева от точки. (window
в глобальном пространстве) - прослушиватели событий значение
this
относится к элементу DOM, на котором вызывалось событие. - когда функция in вызывается с помощью
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
пример прослушивателей событий:
document.querySelector('.foo').addEventListener('click', function () {
console.log(this); // This refers to the DOM element the eventListener was invoked from
})
document.querySelector('.foo').addEventListener('click', () => {
console.log(this); // Tip, es6 arrow function don't have their own binding to the this v
}) // Therefore this will log the global object
.foo:hover {
color: red;
cursor: pointer;
}
<div class="foo">click me</div>
пример конструктора:
function Person (name) {
this.name = name;
}
const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object
console.log(me.name);
// Therefore, the name property was placed on the object created with new keyword.