Как работает это ключевое слово?

1310

Я заметил, что нет четкого объяснения того, что такое thisключевое слово и как оно правильно (и неправильно) используется в JavaScript на сайте переполнения стека.

Я был свидетелем очень странного поведения с ним и не смог понять, почему это произошло.

Как thisработает и когда его следует использовать?

Максим Гершкович
источник
6
Я нашел это, когда погуглил «это» quirksmode.org/js/this.html
Вай Вонг
2
Питер Мишо выступает против использования this peter.michaux.ca/articles/javascript-widgets-without-this
Марселя Корпеля
1
Обзор MDN не половина плохо ... developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/...
Дат
2
Интересное объяснение thisключевого слова: rainsoft.io/gentle-explanation-of-this-in-javascript
Дмитрий Павлутин

Ответы:

1351

Я рекомендую сначала прочитать статью Майка Веста « Область применения в JavaScript ( зеркало )». Это отличное, дружественное введение в концепции thisи области видимости в JavaScript.

Как только вы начинаете привыкать this, правила на самом деле довольно просты. Стандарт ECMAScript 5.1 определяет this:

§11.1.1this ключевое слово

В 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(...);косвенный вызов eval(). Смотрите ответ Чака на (1, eval) ('this') против eval ('this') в JavaScript? и ECMA-262-5 Дмитрия Сошникова в деталях. Глава 2. Строгий режим. когда вы можете использовать косвенный eval()вызов.

Ввод кода функции

Это происходит при вызове функции. Если функция вызывается для объекта, такого как in obj.myMethod()или его эквивалент obj["myMethod"](), тогда ThisBinding устанавливается на объект ( objв примере; §13.2.1 ). В большинстве других случаев ThisBinding устанавливается на глобальный объект ( §10.4.3 ).

Причина написания «в большинстве других случаев» заключается в том, что существует восемь встроенных функций ECMAScript 5, которые позволяют указывать ThisBinding в списке аргументов. Эти специальные функции принимают так называемое, thisArgкоторое становится ThisBinding при вызове функции ( §10.4.3 ).

Эти специальные встроенные функции:

  • Function.prototype.apply( thisArg, argArray )
  • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Array.prototype.every( callbackfn [ , thisArg ] )
  • Array.prototype.some( callbackfn [ , thisArg ] )
  • Array.prototype.forEach( callbackfn [ , thisArg ] )
  • Array.prototype.map( callbackfn [ , thisArg ] )
  • Array.prototype.filter( callbackfn [ , thisArg ] )

В случае Function.prototypeфункций они вызываются для объекта функции, но вместо установки ThisBinding для объекта функции ThisBinding устанавливается в thisArg.

В случае Array.prototypeфункций заданный callbackfnвызывается в контексте выполнения, где ThisBinding установлен, thisArgесли предоставляется; в противном случае, к глобальному объекту.

Это правила для простого JavaScript. Когда вы начинаете использовать библиотеки JavaScript (например, jQuery), вы можете обнаружить, что некоторые библиотечные функции манипулируют значением this. Разработчики этих библиотек JavaScript делают это, потому что это имеет тенденцию поддерживать наиболее распространенные варианты использования, и пользователи библиотеки обычно считают такое поведение более удобным. При передаче функций обратного вызова, ссылающихся thisна библиотечные функции, вы должны ссылаться на документацию для любых гарантий того, каково значение того this, когда вызывается функция.

Если вам интересно, как библиотека JavaScript манипулирует значением this, библиотека просто использует одну из встроенных функций JavaScript, принимающих a 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в среде, в которой определена функция стрелки.

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

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

  1. Какова стоимость thisв отмеченной линии? Почему?

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

    if (true) {
        // What is `this` here?
    }
  2. Каково значение 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);
      

  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не вызывается для объекта, поэтому 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);
      

Daniel Trebbien
источник
6
@Ali: Это ссылки на разделы в редакции 5.1 стандарта ECMAScript, ECMA-262 . Я предоставляю их, чтобы вы могли прочитать Стандарт для технических деталей, если хотите.
Даниэль Треббиен
1
Я думаю, что @supertonsky прав насчет # 2 - если myFun () вызывается из глобальной области, а не как метод объекта, «this» будет глобальным объектом, так что формулировка вопроса имеет значение. Кстати, мне очень нравится идея использовать mouseover, чтобы получить ответ на что-то вроде этого.
user655489
2
Но, jsfiddle.net/H4LYm/2 показывает, что в setTimeoutпримере есть thisо window(global).
Кевин Мередит
2
Исходя из Python, можно было бы представить уровень разочарования, которое я испытал, когда наткнулся на 3-й пример. SMH
Marius Mucenicu
1
Этот ответ, вероятно, следует обновить, чтобы отразить реальность ES2020, даже если изменения являются только терминологическими.
Бен Астон
157

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

Ниже я опробовал все то, что мы сделали с Object и 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's 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's prototype but 
//`this.a` inside fun() retrieves obj3.a   

6. Внутри функций call (), apply () и bind ()

  • Все эти методы определены на Function.prototype.
  • Эти методы позволяют написать функцию один раз и вызвать ее в другом контексте. Другими словами, они позволяют указать значение, thisкоторое будет использоваться во время выполнения функции. Они также принимают любые параметры, которые будут переданы исходной функции, когда она вызывается.
  • fun.apply(obj1 [, argsArray])Устанавливает obj1в качестве значения thisinside fun()и вызывает fun()передаваемые элементы в argsArrayкачестве аргументов.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Устанавливает obj1в качестве значения thisinside 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немедленно вызывает функцию в указанном контексте и с указанными аргументами. С другой стороны, 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 
Mahesha999
источник
«Когда вы используете это внутри функции, определенной в глобальном контексте, она все еще привязана к глобальному объекту, поскольку функция фактически сделана методом глобального контекста». это неверно. это определяется тем, как функция вызывается или bind , а не тем, где она определена. Вызов любой функции без базовой ссылки («контекста») по умолчанию возвращает глобальный объект или остается неопределенным в строгом режиме.
RobG
@RobG хм, может быть, но я нашел это на MDN : в этом случае значение thisне устанавливается вызовом. Поскольку код не находится в строгом режиме, значение thisвсегда должно быть объектом, поэтому по умолчанию используется глобальный объект. И на самом деле именно поэтому я подумал, что мы можем напрямую сделать вызов window.f1(), так что средство f1()уже прикреплено к windowобъекту, я имею в виду до вызова. Я неправильно понял?
Mahesha999
Я комментировал (возможно, не совсем ясно), как вы связали настройку этого с «функция на самом деле сделана методом глобального контекста», как если бы она была вызвана window.fn, но это не так. по умолчанию это глобальный объект, потому что в вызове не использовалась базовая ссылка, а не из-за того, где определена функция (так что это все равно устанавливается тем, как была вызвана функция). Если вы явно вызываете его с помощью window.fn, то вы устанавливаете это в окно . Тот же результат, другой способ сделать это. :-)
RobG
«выше я поставил слово немедленно ...» нет, ты не сделал. Можете ли вы исправить это так, чтобы ошибка была исправлена? Это кажется семантическим для ответа, и поэтому я не могу продолжить чтение, пока ошибка не будет исправлена ​​из-за боязни узнать что-то неправильное.
TylerH
@TylerH сделайте Ctrl + F на этой странице в своем браузере, чтобы найти строку «немедленная» (включая двойные кавычки). Я думаю, что она есть, если я вас неправильно понимаю
Mahesha999
64

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

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

Если an Objectсодержит свойство, которое содержит Function, свойство называется методом. Этот метод, при вызове, всегда будет иметь свою thisпеременную равной тому, с которой Objectон связан. Это верно как для строгих, так и для нестрогих режимов.

Обратите внимание, что если метод хранится (или, скорее, копируется) в другой переменной, ссылка на thisболее не сохраняется в новой переменной. Например:

// continuing with the previous code snippet

var myVar = myObj.logThis;
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будет присвоен прототип Person.prototype. Это означает, что любой метод или свойство в Personпрототипе будет доступно для всех экземпляров Person, включая awal.
  4. Сама функция Personтеперь вызывается; thisбыть ссылкой на недавно построенный объект awal.

Довольно просто, а?

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

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

Так что да, поскольку functions также 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принять, что он принимает только два параметра: 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заранее заданными параметрами. Давайте рассмотрим пример, чтобы лучше понять это:

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будет возвращать саму недавно созданную функцию, готовую к вызову.

Дополнительные вещи, скопируйте это

Иногда вам не нравится тот факт, что 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. Умно, а?

Индекс:

  1. Что удерживается thisпо умолчанию?
  2. Что если мы вызовем функцию как метод с нотацией Object-dot?
  3. Что если мы используем newключевое слово?
  4. Как мы манипулируем thisс callи apply?
  5. Использование bind.
  6. Копирование thisдля решения проблем вложенных областей.
user3459110
источник
47

«это» все о сфере. Каждая функция имеет свою область видимости, и поскольку все в JS является объектом, даже функция может сохранять некоторые значения в себе, используя «this». ООП 101 учит, что «это» применимо только к экземплярам объекта. Поэтому каждый раз, когда функция выполняется, новый «экземпляр» этой функции имеет новое значение «this».

Большинство людей смущаются, когда пытаются использовать «this» внутри анонимных функций закрытия, таких как:

(функция (значение) {
    this.value = значение;
    $ (». Некоторые-элементы). Каждый (функция (ELT) {
        elt.innerHTML = this.value; // э-э-э! возможно неопределенный
    });
}) (2);

Так что здесь, внутри each (), «this» не содержит «значение», которого вы ожидаете (от

this.value = значение;
над ним). Таким образом, чтобы преодолеть эту (не каламбур) проблему, разработчик может:

(функция (значение) {
    var self = this; // небольшой изменение
    self.value = значение;
    $ (». Некоторые-элементы). Каждый (функция (ELT) {
        elt.innerHTML = self.value; // фу! == 2
    });
}) (2);

Попробуйте это; вы начнете любить эту модель программирования

arunjitsingh
источник
6
«все в JS является объектом» не соответствует действительности, JavaScript также имеет примитивные значения, см. bclary.com/2004/11/07/#a-4.3.2
Марсель Корпель
6
Кажется, что примитивные значения имеют некоторые методы, такие как String # substring (), Number # toString () и т. Д. Поэтому, возможно, не с той же номенклатурой, что и в этой статье, они действительно ведут себя так, как если бы они были объектами (они все прототипы, т.е. String # substring (), действительно: String.prototype.substring = function () {...}). Пожалуйста, поправьте меня, если я ошибаюсь.
arunjitsingh
12
thisКлючевое слово не имеет ничего общего с размахом. Кроме того, это имеет значение также в функциях, которые не являются свойствами объектов.
Берги
1
@ arunjitsingh - есть две школы мысли об этом. Мне нравится тот, который говорит, что « все является объектом, но некоторые могут быть представлены примитивами для удобства ». ;-)
RobG
9
thisэто не все о сфере. Это ВСЕ о контексте выполнения, который отличается от контекста. JavaScript имеет лексическую область действия (то есть область действия определяется местоположением кода), но thisопределяется тем, как вызывается функция, в которой он содержится, а не тем, где находится эта функция.
Скотт Маркус
16

Так как эта тема увеличилась, я собрал несколько пунктов для читателей, плохо знакомых с этой 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 не присваивается значение, пока объект не вызовет функцию, в которой он определен. В глобальной области видимости все глобальные переменные и функции определены для windowобъекта. Следовательно, thisв глобальной функции ссылается (и имеет значение) глобальный windowобъект.

Когда use strict, thisв глобальном , так и в анонимных функциях, которые не связаны с каким - либо объектом имеет значение undefined.

thisКлючевое слово наиболее неправильно , когда: 1) заимствовать метод , который использует this, 2) назначить метод , который использует thisна переменный, 3) функции , которая использует thisпередаются в качестве функции обратного вызова, и 4) thisиспользуются внутри крышки - внутренняя функция. (2)

Таблица

Что держит будущее

Определяемые в скрипте ECMA 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)


Ссылки:

  1. Это и прототипы объектов , Кайл Симпсон. © 2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Ангус Кролл - http://goo.gl/Z2RacU
carlodurso
источник
16

thisв JavaScript всегда относится к «владельцу» функции, которая выполняется .

Если явный владелец не определен, то указывается самый верхний владелец, объект окна.

Так что если бы я сделал

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

thisбудет относиться к элементу объекта. Но будьте осторожны, многие люди совершают эту ошибку.

<element onclick="someKindOfFunction()">

В последнем случае вы просто ссылаетесь на функцию, а не передаете ее элементу. Следовательно, thisбудем ссылаться на объект окна.

Seph
источник
15

Каждый контекст выполнения в javascript имеет параметр this, который устанавливается:

  1. Как вызывается функция (в том числе как метод объекта, использование call и apply , использование new )
  2. Использование связывания
  3. Лексически для функций стрелок (они принимают this из своего внешнего контекста выполнения)
  4. Находится ли код в строгом или нестрогом режиме
  5. Был ли код вызван с помощью eval

Вы можете установить значение этого с помощью func.call, func.applyили func.bind.

По умолчанию, и что смущает большинство новичков, когда слушатель вызывается после того, как событие вызвано в элементе DOM, значение this функции является элементом DOM.

jQuery делает это тривиальным, чтобы изменить с jQuery.proxy.

болван
источник
9
Правильнее будет сказать, что каждый вызов функции имеет область видимости. Другими словами, что сбивает с толку thisв Javascript то, что это не внутреннее свойство самой функции, а скорее артефакт того, как вызывается функция.
Заостренный
@ Спасибо, спасибо. то, что вызывает наибольшую путаницу в js, это тот факт, что во всех языках, использовавшихся ранее (c #, c ++), - этим нельзя манипулировать n всегда указывает на экземпляр объекта, тогда как в js это зависит и может быть изменено при вызове функции , используя func.call, и func.bindт.д. - Sushil
Sushil
2
thisникак не ссылаться на область действия функции. thisбудет ссылаться на конкретный объект (или, возможно, undefined), который, как вы сказали, можно изменить с помощью .call()или .apply(). Область действия функции (по сути, когда она упрощена), к каким переменным она имеет доступ, и это полностью зависит от того, где функция объявлена ​​и не может быть изменена.
nnnnnn
@Pointy: «Правильнее будет сказать, что у каждого вызова функции есть область действия». Еще правильнее сказать, что функции (и теперь блоки) имеют область видимости , вызовы функций имеют контекст . Область действия определяет, какие идентификаторы могут использоваться кодом в этой области. Контекст определяет, с чем связаны эти идентификаторы.
TJ Crowder
1
«Каким бы ни был этот охват, на него ссылается« это »». Нет, thisи область действия не имеет ничего общего друг с другом в ES5 и ранее (например, когда этот ответ был написан). В ES2015 (он же ES6) thisи область видимости связаны одним довольно минимальным способом с функциями стрелок (функция thisin arrow наследуется от включающей области видимости), но thisникогда не ссылается на область.
TJ Crowder
10

Вот один хороший источник 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предоставляется a (см. Далее), как в узле, так и в браузере, используя 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"
  • 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для доступа 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>
zangw
источник
9

Даниэль, классное объяснение! Пара слов об этом и хороший список thisуказателей контекста выполнения в случае обработчиков событий.

В двух словах, thisв JavaScript указывается объект, от которого (или из чьего контекста выполнения) была запущена текущая функция, и она всегда доступна только для чтения, в любом случае вы не можете установить ее (такая попытка будет заканчиваться «Неверный левой рукой»). сторона в сообщении присваивания.

Для обработчиков событий: встроенные обработчики событий, такие как <element onclick="foo">, переопределяют любые другие обработчики, присоединенные ранее и ранее, поэтому будьте осторожны, и лучше вообще избегать делегирования встроенных событий. И спасибо Zara Alaverdyan, которая вдохновила меня на этот список примеров через несогласные дебаты :)

  • el.onclick = foo; // in the foo - obj
  • el.onclick = function () {this.style.color = '#fff';} // obj
  • el.onclick = function() {doSomething();} // In the doSomething - Window
  • el.addEventListener('click',foo,false) // in the foo - obj
  • el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
  • <button onclick="this.style.color = '#fff';"> // obj
  • <button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
Арман МакХитариан
источник
9

Существует много путаницы в отношении того, как это ключевое слово интерпретируется в JavaScript. Надеюсь, эта статья положит конец всем раз и навсегда. И многое другое. Пожалуйста, внимательно прочитайте всю статью. Будьте предупреждены, что эта статья длинная.

Независимо от контекста, в котором он используется, «this» всегда ссылается на «текущий объект» в Javascript. Однако то, чем является «текущий объект», зависит от контекста . Контекст может быть точно 1 из 6 следующих:

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

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

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

    Вне всех функций (т. Е. В глобальном контексте) «текущий объект» (и, следовательно, значение «this» ) всегда является объектом «окна» для браузеров.

  2. Внутренний прямой вызов «Не связанная функция» :

    Внутри прямого вызова «Не связанная функция» объект, вызвавший вызов функции, становится «текущим объектом» (и, следовательно, значением «this» ). Если функция вызывается без явного текущего объекта , текущий объект является либо «оконным» объектом (для нестрого режима), либо неопределенным (для строгого режима). Любая функция (или переменная), определенная в глобальном контексте, автоматически становится свойством объекта «окно». Например, предположим, что функция определяется в глобальном контексте как

    function UserDefinedFunction(){
        alert(this)
        }

    оно становится свойством объекта окна, как если бы вы определили его как

    window.UserDefinedFunction=function(){
      alert(this)
    }  

    В «Non Strict Mode», вызов / Вызов этой функции непосредственно через «UserDefinedFunction ()» будет автоматически вызывать / ссылаться на него , как «window.UserDefinedFunction ()» делает «окно» , как «текущий объект» (и , следовательно , значение " this " ) внутри " UserDefinedFunction ". Вызов этой функции в" не строгом режиме "приведет к следующему

    UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()

    В «Строгом режиме» вызов / вызов функции напрямую через «UserDefinedFunction ()» будет «НЕ» автоматически вызывать / вызывать ее как «window.UserDefinedFunction ()». Подразумевает «текущий объект» (и значение «this» ) внутри "UserDefinedFunction" должно быть неопределенным . Вызов этой функции в «Строгом режиме» приведет к следующему

    UserDefinedFunction() // displays undefined

    Однако его явный вызов с использованием объекта window должен привести к следующему

    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" были показаны как неопределенные, поскольку o1 не определяет эти свойства

    Точно так же , когда «UserDefinedFunction» был вызван через o2 , «этот» принимает значение o2 и значение его свойства «в» и «г» получить displayed.The значение «а» и «б» было показано , как определено , как о2 делает не определять эти свойства.

  3. Внутри косвенного вызова «Не связанная функция» вызов через functionName.call и functionName.apply :

    Когда «Non Bound Function» вызывается через functionName.call или functionName.apply , «текущий объект» (и, следовательно, значение «this» ) устанавливается равным значению параметра «this» (первого параметра), передаваемого для вызова / применить . Следующий код демонстрирует то же самое.

    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 Bound Function» может быть изменено с помощью call / apply . Кроме того, если параметр «this» явно не передан в call / apply , «текущий объект» (и, следовательно, значение «this») устанавливается в «window» в нестрогом режиме и «undefined» в строгом режиме.

  4. Внутри вызова «Связанная функция» (то есть функция, которая была связана вызовом 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» ) устанавливается в «window» в нестрогом режиме и «undefined» в строгом режиме. Еще кое-что. Привязка уже связанной функции не меняет значение «this» . Он остается установленным в качестве значения, установленного первой функцией связывания.

  5. При создании объекта через «новый» :

    Внутри функции конструктора «текущий объект» (и, следовательно, значение «этого» ) ссылается на объект, который в данный момент создается через «новый», независимо от состояния привязки функции. Однако, если конструктор является связанной функцией, он должен вызываться с предопределенным набором аргументов, установленным для связанной функции.

  6. Внутри встроенного обработчика событий DOM :

    Пожалуйста, посмотрите на следующий фрагмент HTML

    <button onclick='this.style.color=white'>Hello World</button>
    <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>

    «Это» в приведенном выше примеры относятся к элементу «Кнопки» и элементу «сОн» соответственно.

    В первом примере цвет шрифта кнопки должен быть установлен белым при нажатии.

    Во втором примере при щелчке элемента «div» он должен вызвать функцию OnDivClick, второй параметр которой ссылается на элемент div, по которому щелкнули. Однако значение «this» в OnDivClick НЕ ДОЛЖНО ссылаться на нажатый элемент div . Он должен быть установлен как «объект окна» или «неопределенный» в нестрогом и строгом режимах соответственно (если OnDivClick является несвязанной функцией ) или установлен в предварительно определенное значение Bound (если OnDivClick является связанной функцией )

Следующее суммирует всю статью

  1. В глобальном контексте «это» всегда относится к объекту «окна»

  2. Всякий раз, когда вызывается функция, она вызывается в контексте объекта ( «текущий объект» ). Если текущий объект явно не указан, текущий объект является «оконным объектом» в строгом режиме и не определен в строгом режиме по умолчанию.

  3. Значение «this» в функции Non Bound является ссылкой на объект, в контексте которого вызывается функция ( «текущий объект» )

  4. Значение «это» в функции Non Bound может быть переопределено вызовом и применением методов функции.

  5. Значение «this» является фиксированным для функции Bound и не может быть переопределено вызовом и применением методов функции.

  6. Привязка и уже связанная функция не изменяют значение «this». Он остается установленным в качестве значения, установленного первой функцией связывания.

  7. Значение «this» в конструкторе - это объект, который создается и инициализируется

  8. Значение «this» в встроенном обработчике событий DOM является ссылкой на элемент, для которого предоставляется обработчик события.

Arup Hore
источник
9

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

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

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


Если возникают проблемы с выявлением this, не спрашивайте себя:

Откуда thisвзято ?

но действительно спросить себя:

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

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

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

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

Дмитрий Павлутин
источник
В дополнение к ссылкам на свой блог, возможно, вы могли бы немного глубже понять, как задание этих вопросов помогает кому-то понять thisключевое слово?
Магнус Линд Окслунд
7

Это лучшее объяснение, которое я видел: понять JavaScripts это с Clarity

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

Существует четыре сценария, в которых это может сбить с толку:

  1. Когда мы передаем метод (который использует это ) в качестве аргумента для использования в качестве функции обратного вызова.
  2. Когда мы используем внутреннюю функцию (замыкание). Важно отметить, что замыкания не могут получить доступ к переменной this этой внешней функции, используя ключевое слово this, потому что переменная this доступна только самой функции, а не внутренним функциям.
  3. Когда метод, основанный на этом , назначается переменной в разных контекстах, в этом случае он ссылается на другой объект, чем первоначально предполагалось.
  4. При использовании этого вместе с привязкой, применением и вызовом методов.

Он приводит примеры кода, объяснения и решения, которые, на мой взгляд, были очень полезны.

Джеймс Дринкард
источник
6

В псевдоклассических терминах, во многих лекциях учат ключевое слово «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;
mrmaclean89
источник
5

thisэто одна из неправильно понятых концепций в JavaScript, потому что она ведет себя немного по-разному в разных местах. Проще говоря, thisотносится к «владельцу» функции, которую мы в настоящее время выполняем .

thisпомогает получить текущий объект (или контекст выполнения), с которым мы работаем. Если вы понимаете , в какой объект текущая функция становится выполнена, вы можете легко понять , какие текущие thisIS

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 of 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, который сгенерировал событие.


Nipuna
источник
5

Значение this зависит от контекста, в котором выполняется функция. Контекст может быть любым объектом или глобальным объектом, то есть окном.

Так что Семантика «этого» отличается от традиционных языков ООП. И это вызывает проблемы: 1. когда функция передается другой переменной (скорее всего, обратному вызову); и 2. когда замыкание вызывается из метода-члена класса.

В обоих случаях это установлено в окно.

Тромба
источник
3

Как это может помочь? (Большая путаница с «этим» в javascript связана с тем, что он, как правило, связан не с вашим объектом, а с текущей областью выполнения - это может быть не совсем так, как это работает, но мне всегда кажется, что это так - см. статью для полного объяснения)

Саймон Гроенволт
источник
1
Было бы лучше сказать, что это связано " с текущим контекстом выполнения ". За исключением ES6 (черновик), это изменяется с помощью функций стрелок, где это разрешается во внешнем контексте выполнения.
RobG
3

Немного информации об этом ключевом слове

Давайте зарегистрируем 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

unclexo
источник
1

это использование для Scope так же, как это

  <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') равно

PRADEEP SINGH Chundawat
источник
1

У меня другой взгляд на this к другим ответам, которые, я надеюсь, будут полезны.

Один из способов взглянуть на JavaScript - это увидеть только 1 способ вызова функции 1 . это

functionObject.call(objectForThis, arg0, arg1, arg2, ...);

Всегда есть какая-то ценность для objectForThis.

Все остальное является синтаксическим сахаром для functionObject.call

Итак, все остальное можно описать тем, как оно переводится на functionObject.call.

Если вы просто вызываете функцию, то thisэто «глобальный объект», который в браузере является окном

function foo() {
  console.log(this);
}

foo();  // this is the window object

Другими словами,

foo();

был эффективно переведен на

foo.call(window);

Обратите внимание, что если вы используете строгий режим, то thisбудетundefined

'use strict';

function foo() {
  console.log(this);
}

foo();  // this is the window object

что значит

Другими словами,

foo();

был эффективно переведен на

foo.call(undefined);

В JavaScript есть операторы типа +и -и *. Существует также точка оператора, который.

.Оператора при использовании функции справа и объекта слева фактически означает «объект в качестве проходаthis к функции.

пример

const bar = {
  name: 'bar',
  foo() { 
    console.log(this); 
  },
};

bar.foo();  // this is bar

Другими словами, bar.foo()переводится наconst temp = bar.foo; temp.call(bar);

Обратите внимание, что не имеет значения, как была создана функция (в основном ...). Все это даст одинаковые результаты

const bar = {
  name: 'bar',
  fn1() { console.log(this); },
  fn2: function() { console.log(this); },
  fn3: otherFunction,
};

function otherFunction() { console.log(this) };

bar.fn1();  // this is bar
bar.fn2();  // this is bar
bar.fn3();  // this is bar

Опять же, все это просто синтаксический сахар для

{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }

Еще одна складка - прототип цепи. При использовании a.bJavaScript сначала выполняется поиск объекта, на который ссылается непосредственно aсвойство b. Еслиb объект не найден, JavaScript будет искать в прототипе объекта, чтобы найтиb .

Существуют различные способы определения прототипа объекта, наиболее распространенным в 2019 году является classключевое слово. Для целей, thisхотя это не имеет значения. Важно то, что, когда он ищет в объекте aсвойство, bесли он находит свойство bв объекте или в цепочке прототипов, если в bитоге оказывается функцией, то применяются те же правила, что и выше. bСсылки на функции будут вызываться с использованием callметода и передачиa как objectForThis, как показано в верхней части этого ответа.

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

function foo() {
  console.log(this);
}

function bar() {
  const objectForThis = {name: 'moo'}
  foo.call(objectForThis);  // explicitly passing objectForThis
}

const obj = {
  bar,
};

obj.bar();  

После перевода использовать call, obj.bar()становится const temp = obj.bar; temp.call(obj);. Когда мы входим в barфункцию, которую мы вызываемfoo но мы явно передаем другой объект для objectForThis, поэтому, когда мы приходим к foothis , этот внутренний объект.

Это то, что эффективно делают bindи =>функции, и функции. Они более синтаксические сахара. Они эффективно создают новую невидимую функцию в точности как barвыше, которая явно устанавливает thisперед вызовом любую указанную функцию. В случае bind thisустанавливается то, что вы передаете bind.

function foo() {
  console.log(this);
}

const bar = foo.bind({name: 'moo'});

// bind created a new invisible function that calls foo with the bound object.

bar();  

// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above

bar.call({name: 'other'});

Обратите внимание, что если functionObject.bindбы не существовало, мы могли бы сделать свое собственное, как это

function bind(fn, objectForThis) {
  return function(...args) {
    return fn.call(objectForthis, ...args);
  };
}

и тогда мы могли бы назвать это так

function foo() {
  console.log(this);
}

const bar = bind(foo, {name:'abc'});

Функции стрелки, =>оператор синтаксический сахар для привязки

const a = () => {console.log(this)};

такой же как

const tempFn = function() {console.log(this)}; 
const a = tempFn.bind(this);

Точно так же bind, создается новая невидимая функция, которая вызывает данную функцию со связанным значением, objectForThisно в отличие bindот объекта, который должен быть связан, является неявным. Это что угодноthis происходит, когда=> оператор используется.

Итак, как и правила выше

const a = () => { console.log(this); }  // this is the global object
'use strict';
const a = () => { console.log(this); }  // this is undefined
function foo() {
  return () => { console.log(this); }
}

const obj = {
  foo,
};
const b = obj.foo();
b();

obj.foo()переводит, const temp = obj.foo; temp.call(obj);что означает, что оператор стрелки внутри fooбудет связываться objс новой невидимой функцией и возвращать ту новую невидимую функцию, которая назначена b. b()будет работать как всегда b.call(window)или b.call(undefined)вызывать новую невидимую функцию, которая была fooсоздана. Эта невидимая функция игнорирует thisпереданные в нее и передаетobj как objectForThis` в функцию стрелки.

Код выше переводится как

function foo() {
  function tempFn() {
    console.log(this);
  }
  return tempFn.bind(this);
}

const obj = {
  foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);

1apply - другая функция, аналогичнаяcall

functionName.apply(objectForThis, arrayOfArgs);

Но с ES6 концептуально вы можете даже перевести это на

functionName.call(objectForThis, ...arrayOfArgs);
GMan
источник
0

Резюме thisJavascript:

  • Значение 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
              
             

Пример слушателей событий:

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.

Виллем ван дер Веен
источник
0

Чтобы правильно понять «это», нужно понимать контекст, сферу и разницу между ними.

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

Контекст : контекст связан с объектами. Это относится к объекту, которому принадлежит функция. Когда вы используете ключевое слово «this» в JavaScript, оно относится к объекту, которому принадлежит функция. Например, внутри функции, когда вы говорите: «this.accoutNumber», вы ссылаетесь на свойство «accoutNumber», которое принадлежит объекту, которому принадлежит эта функция.

Если у объекта «myObj» есть метод «getMyName», то когда ключевое слово «this» в JavaScript используется внутри «getMyName», он ссылается на «myObj». Если функция «getMyName» выполнялась в глобальной области видимости, то «this» относится к объекту окна (кроме строгого режима).

Теперь давайте посмотрим на пример:

    <script>
        console.log('What is this: '+this);
        console.log(this);
    </script>

Runnig abobve код в выводе браузера будет: введите описание изображения здесь

В соответствии с выводом, который вы находитесь внутри контекста объекта окна, также видно, что прототип окна ссылается на объект.

Теперь давайте попробуем внутри функции:

    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

Вывод:

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

Теперь давайте создадим наш собственный объект. В javascript вы можете создавать объекты разными способами.

 <script>
        var firstName = "Nora";
        var lastName = "Zaman";
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printNameGetContext:function(){
                console.log(firstName + " "+lastName);
                console.log(this.firstName +" "+this.lastName);
                return this;
            }
        }

      var context = myObj.printNameGetContext();
      console.log(context);
    </script>

Вывод: введите описание изображения здесь

Таким образом, из приведенного выше примера мы обнаружили, что ключевое слово «this» относится к новому контексту, связанному с myObj, и myObject также имеет цепочку прототипов для Object.

Пойдем кинем еще один пример:

<body>
    <button class="btn">Click Me</button>
    <script>
        function printMe(){
            //Terminal2: this function declared inside window context so this function belongs to the window object.
            console.log(this);
        }
        document.querySelector('.btn').addEventListener('click', function(){
            //Terminal1: button context, this callback function belongs to DOM element 
            console.log(this);
            printMe();
        })
    </script>
</body>

вывод: имеет смысл правильно? (читать комментарии) введите описание изображения здесь

Если у вас возникли проблемы с пониманием приведенного выше примера, давайте попробуем воспользоваться нашим собственным обратным вызовом;

<script>
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printName:function(callback1, callback2){
                //Attaching callback1 with this myObj context
                this.callback1 = callback1;
                this.callback1(this.firstName +" "+this.lastName)
                //We did not attached callback2 with myObj so, it's reamin with window context by default
                callback2();
                /*
                 //test bellow codes
                 this.callback2 = callback2;
                 this.callback2();
                */
            }
        }
        var callback2 = function (){
            console.log(this);
        }
        myObj.printName(function(data){
            console.log(data);
            console.log(this);
        }, callback2);
    </script>

вывод: введите описание изображения здесь

Теперь давайте разберемся в Scope, Self, IIFE и THIS, как ведет себя

       var color = 'red'; // property of window
       var obj = {
           color:'blue', // property of window
           printColor: function(){ // property of obj, attached with obj
               var self = this;
               console.log('In printColor -- this.color: '+this.color);
               console.log('In printColor -- self.color: '+self.color);
               (function(){ // decleard inside of printColor but not property of object, it will executed on window context.
                    console.log(this)
                    console.log('In IIFE -- this.color: '+this.color);
                    console.log('In IIFE -- self.color: '+self.color); 
               })();

               function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
                    console.log('nested fun -- this.color: '+this.color);
                    console.log('nested fun -- self.color: '+self.color);
               }

               nestedFunc(); // executed on window context
               return nestedFunc;
           }
       };

       obj.printColor()(); // returned function executed on window context
   </script> 

Вывод довольно классный, верно? введите описание изображения здесь

повелитель
источник
-1

Простой ответ:

Это ключевое слово всегда зависит от контекста вызова. Они упомянуты ниже.

  1. ФУНКЦИЯ ВЫЗЫВАЕТСЯ С НОВЫМ КЛЮЧОМ

    Если функция вызывается с ключевым словом NEW, тогда THIS будет привязан к вновь созданному объекту.

    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output "BMW"

    Выше это будет связано с объектом 'myCar'

  2. ФУНКЦИЯ ВЫЗЫВАЕТСЯ ТОЛЬКО С ИСПОЛЬЗОВАНИЕМ МЕТОДОВ ВЫЗОВА И ПРИМЕНЕНИЯ.

    В этом случае ЭТО будет связано с объектом, который явно передается функции.

    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.
  3. ЕСЛИ ФУНКЦИЯ ВЫЗЫВАЕТСЯ С ОБЪЕКТОМ, ТОЛЬКО ПОСЛЕ ТОГО, ЧТО ЭТО БУДЕТ СВЯЗАНО С ЭТИМ ОБЪЕКТОМ

    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)
  4. КОГДА ФУНКЦИЯ ВЫЗВАНА БЕЗ ЛЮБОГО КОНТЕКСТА, ЭТО БУДЕТ СВЯЗАНО С ГЛОБАЛЬНЫМ ОБЪЕКТОМ

    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
  5. В СТРОГО РЕЖИМЕ ЭТО БУДЕТ НЕ УКАЗАНО

    function setName(name){
        "use strict"
        return this.name;
    }
    setName(); //WILL BE ERROR SAYING name IS UNDEFINED. 
ПАЛЛАМОЛЛА САИ
источник