Как работает ключевое слово" 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);

просто для удовольствия, Проверьте свое понимание с некоторыми примерами

чтобы показать ответы, наведите курсор мыши на светло-желтые коробки.

  1. каково значение this по отмеченной линии? Почему?

    window - отмеченная строка оценивается в начальном глобальном контексте выполнения.

    if (true) {
        // What is `this` here?
    }
    
  2. каково значение 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);
      
  3. каково значение 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);
      
  4. каково значение this по отмеченной линии? Почему?

    window

    это было сложно. При оценке кода eval this и obj. Однако в коде eval myFun is не вызывается объект, поэтому ThisBinding имеет значение window для вызова.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
    
  5. каково значение 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..." >) элемента, он относится к элементу.
  • использование this косвенно через другую функцию, вызываемую внутри функции обработки событий или свойства события, разрешает глобальный объект window.
  • то же самое выше поведение достигается при присоединении функции к обработчику событий с помощью метода модели регистрации событий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>

в 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, включая Arrays и Functions). Возьмите следующий код для образец.

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 ключевое слово.

  1. вызов функции с new ключевое слово немедленно инициализирует Object типа Person.
  2. в конструктор этого Object имеет свой конструктор, установленный в Person. Кроме того, обратите внимание, что typeof awal вернутся Object только.
  3. новый Object будет назначена protoype из Person.prototype. Это означает, что любой метод или свойство в Person прототип будет доступен для всех экземпляров Person, включая awal.
  4. функции Person сам теперь вызывается;this быть ссылкой на недавно построенный объект awal.

довольно straighforward, а?

обратите внимание, что официальная спецификация ECMAScript не указывает, что такие типы функций являются актуальными constructor функции. Это просто нормальные функции, и new можно использовать в любой функции. Просто мы используем их как таковые и называем только таковыми.

вызов функций на функции : call и apply

так что да, начиная с functions также 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 не присваивается значение пока объект не вызовет функцию, в которой она определена. В глобальной области все глобальные переменные и функции определяются на


функции контекст исполнения в javascript есть область контекст этой параметр, который задается:
  1. как вызывается функция (в том числе в качестве метода объекта, использование вызов и применить, использование новая)
  2. использование bind
  3. лексически для функций стрелки (они принимают этой 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 следующее:

  1. глобальные (т. е. вне всех функций)
  2. Внутри Прямой" Не Связанной Функции " Вызов (т. е. функция, которая имеет не было связывается по телефону functionName.bind)
  3. Внутри Косвенной " Non Связанной Функции" Звоните через functionName.звоните и functionName.применить
  4. Внутри" Связанной Функции " Вызов (т. е. функция привязан по телефону functionName.bind)
  5. при создании объекта через "new"
  6. внутри встроенного обработчика событий DOM

в ниже описывается каждый из этих контекстов один за другим:

  1. Глобальный Контекст (т. е. вне всех функций):

    вне всех функций (т. е. в глобальном контексте) в "текущий объект" (и, следовательно, стоимость "этот") всегда окно""окно""


вероятно, самая подробная и исчерпывающая статья о this следующий:

нежное объяснение ключевого слова "this" в JavaScript

идея this должен понимать, что типы вызовов функций имеют важное значение для настройки this значение.


при возникновении проблем с идентификацией this, не задайте себе вопрос:

где this принято от?

но do задайте себе вопрос:

как функция вызывается?

для функции стрелки (особый случай прозрачности контекста) спросите себя:

какое значение имеет this где функция стрелка определена?

это мышление правильно при работе с this и спасет вас от головная боль.


Это лучшее объяснение, которое я видел. Понять JavaScripts этой ясность

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

есть четыре условия, где этой можно запутаться:

  1. когда мы передаем метод (который использует этой) в качестве параметра используется в качестве функции обратного вызова.
  2. другой случай, когда это неправильно понято, - это когда мы используем внутренний метод (закрытие). Важно отметить, что закрытие не может получить доступ к внешней функции этой переменной с помощью это ключевое слово, потому что эта переменная доступна только самой функцией, а не внутренними функциями.
  3. используя этой когда метод присваивается переменной. The этой значение привязано к другому объекту, если мы назначаем метод, который использует это переменной
  4. используя этой при использовании методов 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, который сгенерировал событие.



значение "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.