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

Jun 27 2010

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

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

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

Ответы

1378 DanielTrebbien Jun 27 2010 at 20:15

Я рекомендую сначала прочитать статью Майка Уэста Scope in JavaScript ( mirror ). Это отличное и удобное введение в концепции 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 ).

2. Ввод кода оценки

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

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

Это происходит при вызове функции. Если функция вызывается для объекта, такого как 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, принимающих 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. См. Существующий канонический вопрос: функция стрелки или объявление / выражения функции: эквивалентны ли они / заменяются ли они? для дополнительной информации. Но вкратце:

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

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

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

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

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

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

  1. Какое значение 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);
  

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

window

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

 <!-- no snippet because, seemingly, eval doesn’t work in snippets -->

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  1. Какое значение 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);
  

168 Mahesha999 Jul 08 2013 at 00:32

В 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. Функции внутреннего вызова (), apply () и bind ().

  • Все эти методы определены на Function.prototype.
  • Эти методы позволяют один раз написать функцию и вызвать ее в другом контексте. Другими словами, они позволяют указать значение, thisкоторое будет использоваться при выполнении функции. Они также принимают любые параметры, передаваемые исходной функции при ее вызове.
  • fun.apply(obj1 [, argsArray])Устанавливается obj1как значение thisвнутри fun()и вызывает fun()передаваемые элементы argsArrayкак аргументы.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Устанавливается obj1в качестве значения thisвнутри fun()и вызывает fun()передачу в arg1, arg2, arg3, ...качестве аргументов.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Возвращает ссылку на функцию funс thisпривязкой внутри fun obj1и параметрами, funпривязанными к указанным параметрам arg1, arg2, arg3,....
  • В настоящее время разница между apply, callи bindдолжно быть , стало очевидным. applyпозволяет указать аргументы, которые будут функционировать как объект, подобный массиву, то есть объект с числовым lengthсвойством и соответствующими неотрицательными целочисленными свойствами. В то время как callпозволяет напрямую указывать аргументы функции. Оба applyи callнемедленно вызывают функцию в указанном контексте и с указанными аргументами. С другой стороны, 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 
66 user3459110 Oct 26 2014 at 22:07

Javascript's this

Simple function invocation

Consider the following function:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

Note that we are running this in the normal mode, i.e. strict mode is not used.

When running in a browser, the value of this would be logged as window. This is because window is the global variable in a web browser's scope.

If you run this same piece of code in an environment like node.js, this would refer to the global variable in your app.

Now if we run this in strict mode by adding the statement "use strict"; to the beginning of the function declaration, this would no longer refer to the global variable in either of the environments. This is done to avoid confusions in strict mode. this would, in this case just log undefined, because that is what it is, it is not defined.

In the following cases, we would see how to manipulate the value of this.

Calling a function on an object

There are different ways to do this. If you have called native methods in Javascript like forEach and slice, you should already know that the this variable in that case refers to the Object on which you called that function (Note that in javascript, just about everything is an Object, including Arrays and Functions). Take the following code for example.

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

If an Object contains a property which holds a Function, the property is called a method. This method, when called, will always have it's this variable set to the Object it is associated with. This is true for both strict and non-strict modes.

Note that if a method is stored (or rather, copied) in another variable, the reference to this is no longer preserved in the new variable. For example:

// continuing with the previous code snippet

var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation

Considering a more commonly practical scenario:

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

The new keyword

Consider a constructor function in 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`

How does this work? Well, let's see what happens when we use the new keyword.

  1. Calling the function with the new keyword would immediately initialize an Object of type Person.
  2. The constructor of this Object has its constructor set to Person. Also, note that typeof awal would return Object only.
  3. This new Object would be assigned the prototype of Person.prototype. This means that any method or property in the Person prototype would be available to all instances of Person, including awal.
  4. The function Person itself is now invoked; this being a reference to the newly constructed object awal.

Pretty straightforward, eh?

Note that the official ECMAScript spec nowhere states that such types of functions are actual constructor functions. They are just normal functions, and new can be used on any function. It's just that we use them as such, and so we call them as such only.

Calling functions on Functions: call and apply

So yeah, since functions are also Objects (and in-fact first class variables in Javascript), even functions have methods which are... well, functions themselves.

All functions inherit from the global Function, and two of its many methods are call and apply, and both can be used to manipulate the value of this in the function on which they are called.

function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);

This is a typical example of using call. It basically takes the first parameter and sets this in the function foo as a reference to thisArg. All other parameters passed to call is passed to the function foo as arguments.
So the above code will log {myObj: "is cool"}, [1, 2, 3] in the console. Pretty nice way to change the value of this in any function.

apply is almost the same as call accept that it takes only two parameters: thisArg and an array which contains the arguments to be passed to the function. So the above call call can be translated to apply like this:

foo.apply(thisArg, [1,2,3])

Note that call and apply can override the value of this set by dot method invocation we discussed in the second bullet. Simple enough :)

Presenting.... bind!

bind is a brother of call and apply. It is also a method inherited by all functions from the global Function constructor in Javascript. The difference between bind and call/apply is that both call and apply will actually invoke the function. bind, on the other hand, returns a new function with the thisArg and arguments pre-set. Let's take an example to better understand this:

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]`

See the difference between the three? It is subtle, but they are used differently. Like call and apply, bind will also over-ride the value of this set by dot-method invocation.

Also note that neither of these three functions do any change to the original function. call and apply would return the value from freshly constructed functions while bind will return the freshly constructed function itself, ready to be called.

Extra stuff, copy this

Sometimes, you don't like the fact that this changes with scope, especially nested scope. Take a look at the following example.

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"
        });
    }
  };

In the above code, we see that the value of this changed with the nested scope, but we wanted the value of this from the original scope. So we 'copied' this to that and used the copy instead of this. Clever, eh?

Index:

  1. What is held in this by default?
  2. What if we call the function as a method with Object-dot notation?
  3. What if we use the new keyword?
  4. How do we manipulate this with call and apply?
  5. Using bind.
  6. Copying this to solve nested-scope issues.
49 arunjitsingh Jun 27 2010 at 21:10

"this" is all about scope. Every function has its own scope, and since everything in JS is an object, even a function can store some values into itself using "this". OOP 101 teaches that "this" is only applicable to instances of an object. Therefore, every-time a function executes, a new "instance" of that function has a new meaning of "this".

Most people get confused when they try to use "this" inside of anonymous closure functions like:

(function(value) {
    this.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = this.value;        // uh oh!! possibly undefined
    });
})(2);

So here, inside each(), "this" doesn't hold the "value" that you expect it to (from

this.value = value;
above it). So, to get over this (no pun intended) problem, a developer could:

(function(value) {
    var self = this;            // small change
    self.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = self.value;        // phew!! == 2 
    });
})(2);

Try it out; you'll begin to like this pattern of programming

18 carlodurso Oct 30 2014 at 10:58

Since this thread has bumped up, I have compiled few points for readers new to this topic.

How is the value of this determined?

We use this similar to the way we use pronouns in natural languages like English: “John is running fast because he is trying to catch the train.” Instead we could have written “… John is trying to catch the train”.

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 is not assigned a value until an object invokes the function where it is defined. In the global scope, all global variables and functions are defined on the window object. Therefore, this in a global function refers to (and has the value of) the global window object.

When use strict, this in global and in anonymous functions that are not bound to any object holds a value of undefined.

The this keyword is most misunderstood when: 1) we borrow a method that uses this, 2) we assign a method that uses this to a variable, 3) a function that uses this is passed as a callback function, and 4) this is used inside a closure — an inner function. (2)

What holds the future

Defined in ECMA Script 6, arrow-functions adopt the this binding from the enclosing (function or global) scope.

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!

While arrow-functions provide an alternative to using bind(), it’s important to note that they essentially are disabling the traditional this mechanism in favor of more widely understood lexical scoping. (1)


References:

  1. this & Object Prototypes, by Kyle Simpson. © 2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU
18 Seph Oct 07 2013 at 02:46

this in JavaScript always refers to the 'owner' of the function that is being executed.

If no explicit owner is defined, then the top most owner, the window object, is referenced.

So if I did

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

element.onclick = someKindOfFunction;

this would refer to the element object. But be careful, a lot of people make this mistake.

<element onclick="someKindOfFunction()">

In the latter case, you merely reference the function, not hand it over to the element. Therefore, this will refer to the window object.

15 blockhead Jun 27 2010 at 20:15

Every execution context in javascript has a this parameter that is set by:

  1. How the function is called (including as an object method, use of call and apply, use of new)
  2. Use of bind
  3. Lexically for arrow functions (they adopt the this of their outer execution context)
  4. Whether the code is in strict or non-strict mode
  5. Whether the code was invoked using eval

You can set the value of this using func.call, func.apply or func.bind.

By default, and what confuses most beginners, when a listener is called after an event is raised on a DOM element, the this value of the function is the DOM element.

jQuery makes this trivial to change with jQuery.proxy.

11 ArmanMcHitarian Apr 23 2013 at 19:57

Daniel, awesome explanation! A couple of words on this and good list of this execution context pointer in case of event handlers.

In two words, this in JavaScript points the object from whom (or from whose execution context) the current function was run and it's always read-only, you can't set it anyway (such an attempt will end up with 'Invalid left-hand side in assignment' message.

For event handlers: inline event handlers, such as <element onclick="foo">, override any other handlers attached earlier and before, so be careful and it's better to stay off of inline event delegation at all. And thanks to Zara Alaverdyan who inspired me to this list of examples through a dissenting debate :)

  • 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)">
11 zangw Nov 29 2015 at 13:01

Here is one good source of this in JavaScript.

Here is the summary:

  • global this

    In a browser, at the global scope, this is the windowobject

    <script type="text/javascript">
      console.log(this === window); // true
      var foo = "bar";
      console.log(this.foo); // "bar"
      console.log(window.foo); // "bar"
    

    In node using the repl, this is the top namespace. You can refer to it as global.

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true
    

    In node executing from a script, this at the global scope starts as an empty object. It is not the same as global

    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
    
  • function this

Except in the case of DOM event handlers or when a thisArg is provided (see further down), both in node and in a browser using this in a function that is not called with new references the global scope…

<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>

If you use use strict;, in which case this will be 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>

If you call a function with new the this will be a new context, it will not reference the global 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 this

Functions you create become function objects. They automatically get a special prototype property, which is something you can assign values to. When you create an instance by calling your function with new you get access to the values you assigned to the prototype property. You access those values using this.

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

Thing.prototype.foo = "bar";

var thing = new Thing(); //logs "bar"
console.log(thing.foo);  //logs "bar"

It is usually a mistake to assign arrays or objects on the prototype. If you want instances to each have their own arrays, create them in the function, not the 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 []
  • object this

You can use this in any function on an object to refer to other properties on that object. This is not the same as an instance created with new.

var obj = {
    foo: "bar",
    logFoo: function () {
        console.log(this.foo);
    }
};

obj.logFoo(); //logs "bar"
  • DOM event this

In an HTML DOM event handler, this is always a reference to the DOM element the event was attached to

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();

Unless you bind the context

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 this

Inside HTML attributes in which you can put JavaScript, this is a reference to the element.

<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
  • eval this

You can use eval to access 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

You can use with to add this to the current scope to read and write to values on this without referring to this explicitly.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    with (this) {
        console.log(foo);
        foo = "foo";
    }
}

var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
  • jQuery this

the jQuery will in many places have this refer to a DOM element.

<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () { console.log(this); //logs <div class="foo... }); $(".foo").on("click", function () {
    console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
    this.click();
});
</script>
9 ArupHore Jan 31 2017 at 15:29

There is a lot of confusion regarding how "this" keyword is interpreted in JavaScript. Hopefully this article will lay all those to rest once and for all. And a lot more. Please read the entire article carefully. Be forewarned that this article is long.

Irrespective of the context in which it is used, "this" always references the "current object" in Javascript. However, what the "current object" is differs according to context. The context may be exactly 1 of the 6 following:

  1. Global (i.e. Outside all functions)
  2. Inside Direct "Non Bound Function" Call (i.e. a function that has not been bound by calling functionName.bind)
  3. Inside Indirect "Non Bound Function" Call through functionName.call and functionName.apply
  4. Inside "Bound Function" Call (i.e. a function that has been bound by calling functionName.bind)
  5. While Object Creation through "new"
  6. Inside Inline DOM event handler

The following describes each of this contexts one by one:

  1. Global Context (i.e. Outside all functions):

    Outside all functions (i.e. in global context) the "current object" (and hence the value of "this") is always the "window" object for browsers.

  2. Inside Direct "Non Bound Function" Call:

    Inside a Direct "Non Bound Function" Call, the object that invoked the function call becomes the "current object" (and hence the value of "this"). If a function is called without a explicit current object, the current object is either the "window" object (For Non Strict Mode) or undefined (For Strict Mode) . Any function (or variable) defined in Global Context automatically becomes a property of the "window" object.For e.g Suppose function is defined in Global Context as

    function UserDefinedFunction(){
        alert(this)
        }
    

    it becomes the property of the window object, as if you have defined it as

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

    In "Non Strict Mode", Calling/Invoking this function directly through "UserDefinedFunction()" will automatically call/invoke it as "window.UserDefinedFunction()" making "window" as the "current object" (and hence the value of "this") within "UserDefinedFunction".Invoking this function in "Non Strict Mode" will result in the following

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

    In "Strict Mode", Calling/Invoking the function directly through "UserDefinedFunction()" will "NOT" automatically call/invoke it as "window.UserDefinedFunction()".Hence the "current object" (and the value of "this") within "UserDefinedFunction" shall be undefined. Invoking this function in "Strict Mode" will result in the following

    UserDefinedFunction() // displays undefined
    

    However, invoking it explicitly using window object shall result in the following

    window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."
    

    Let us look at another example. Please look at the following code

     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
    

    In the above example we see that when "UserDefinedFunction" was invoked through o1, "this" takes value of o1 and the value of its properties "a" and "b" get displayed. The value of "c" and "d" were shown as undefined as o1 does not define these properties

    Similarly when "UserDefinedFunction" was invoked through o2, "this" takes value of o2 and the value of its properties "c" and "d" get displayed.The value of "a" and "b" were shown as undefined as o2 does not define these properties.

  3. Inside Indirect "Non Bound Function" Call through functionName.call and functionName.apply:

    When a "Non Bound Function" is called through functionName.call or functionName.apply, the "current object" (and hence the value of "this") is set to the value of "this" parameter (first parameter) passed to call/apply. The following code demonstrates the same.

    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
    

    The above code clearly shows that the "this" value for any "NON Bound Function" can be altered through call/apply. Also,if the "this" parameter is not explicitly passed to call/apply, "current object" (and hence the value of "this") is set to "window" in Non strict mode and "undefined" in strict mode.

  4. Inside "Bound Function" Call (i.e. a function that has been bound by calling functionName.bind):

    A bound function is a function whose "this" value has been fixed. The following code demonstrated how "this" works in case of bound function

    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
    

    As given in the code above, "this" value for any "Bound Function" CANNOT be altered through call/apply. Also, if the "this" parameter is not explicitly passed to bind, "current object" (and hence the value of "this" ) is set to "window" in Non strict mode and "undefined" in strict mode. One more thing. Binding an already bound function does not change the value of "this". It remains set as the value set by first bind function.

  5. While Object Creation through "new":

    Inside a constructor function, the "current object" (and hence the value of "this") references the object that is currently being created through "new" irrespective of the bind status of the function. However if the constructor is a bound function it shall get called with predefined set of arguments as set for the bound function.

  6. Inside Inline DOM event handler:

    Please look at the following HTML Snippet

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

    The "this" in above examples refer to "button" element and the "div" element respectively.

    In the first example, the font color of the button shall be set to white when it is clicked.

    In the second example when the "div" element is clicked it shall call the OnDivClick function with its second parameter referencing the clicked div element. However the value of "this" within OnDivClick SHALL NOT reference the clicked div element. It shall be set as the "window object" or "undefined" in Non strict and Strict Modes respectively (if OnDivClick is an unbound function) or set to a predefined Bound value (if OnDivClick is a bound function)

The following summarizes the entire article

  1. In Global Context "this" always refers to the "window" object

  2. Whenever a function is invoked, it is invoked in context of an object ("current object"). If the current object is not explicitly provided, the current object is the "window object" in NON Strict Mode and "undefined" in Strict Mode by default.

  3. The value of "this" within a Non Bound function is the reference to object in context of which the function is invoked ("current object")

  4. The value of "this" within a Non Bound function can be overriden by call and apply methods of the function.

  5. The value of "this" is fixed for a Bound function and cannot be overriden by call and apply methods of the function.

  6. Binding and already bound function does not change the value of "this". It remains set as the value set by first bind function.

  7. The value of "this" within a constructor is the object that is being created and initialized

  8. The value of "this" within an inline DOM event handler is reference to the element for which the event handler is given.

9 DmitriPavlutin Nov 08 2016 at 19:17

Probably the most detailed and comprehensive article on this is the following:

Gentle explanation of 'this' keyword in JavaScript

The idea behind this is to understand that the function invocation types have the significant importance on setting this value.


When having troubles identifying this, do not ask yourself:

Where is this taken from?

but do ask yourself:

How is the function invoked?

For an arrow function (special case of context transparency) ask yourself:

What value has this where the arrow function is defined?

This mindset is correct when dealing with this and will save you from headache.

7 JamesDrinkard Jul 13 2016 at 02:03

This is the best explanation I've seen: Understand JavaScripts this with Clarity

The this reference ALWAYS refers to (and holds the value of) an object—a singular object—and it is usually used inside a function or a method, although it can be used outside a function in the global scope. Note that when we use strict mode, this holds the value of undefined in global functions and in anonymous functions that are not bound to any object.

There are Four Scenarios where this can be confusing:

  1. When we pass a method (that uses this) as an argument to be used as a callback function.
  2. When we use an inner function (a closure). It is important to take note that closures cannot access the outer function’s this variable by using the this keyword because the this variable is accessible only by the function itself, not by inner functions.
  3. When a method which relies on this is assigned to a variable across contexts, in which case this references another object than originally intended.
  4. When using this along with the bind, apply, and call methods.

He gives code examples, explanations, and solutions, which I thought was very helpful.

6 Nipuna Aug 09 2014 at 16:22

this is one of the misunderstood concept in JavaScript because it behaves little differently from place to place. Simply, this refers to the "owner" of the function we are currently executing.

this helps to get the current object (a.k.a. execution context) we work with. If you understand in which object the current function is getting executed, you can understand easily what 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

Above we create 3 variables with same name 'val'. One in global context, one inside obj and the other inside innerMethod of obj. JavaScript resolves identifiers within a particular context by going up the scope chain from local go global.


Few places where this can be differentiated

Calling a method of a object

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

When line1 is executed, JavaScript establishes an execution context (EC) for the function call, setting this to the object referenced by whatever came before the last ".". so in the last line you can understand that a() was executed in the global context which is the window.

With Constructor

this can be used to refer to the object being created

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

When new Person() is executed, a completely new object is created. Person is called and its this is set to reference that new object.

Function call

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 

If we miss new keyword, whatIsThis referes to the most global context it can find(window)

With event handlers

If the event handler is inline, this refers to global object

<script type="application/javascript">
    function click_handler() {
        alert(this); // alerts the window object
    }
</script>

<button id='thebutton' onclick='click_handler()'>Click me!</button>

When adding event handler through JavaScript, this refers to DOM element that generated the event.


  • You can also manipulate the context using .apply() .call() and .bind()
  • JQuery proxy is another way you can use to make sure this in a function will be the value you desire. (Check Understanding $.proxy(), jQuery.proxy() usage)
  • What does var that = this means in JavaScript
6 mrmaclean89 Sep 17 2017 at 05:11

In pseudoclassical terms, the way many lectures teach the 'this' keyword is as an object instantiated by a class or object constructor. Each time a new object is constructed from a class, imagine that under the hood a local instance of a 'this' object is created and returned. I remember it taught like 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;
5 Trombe Jul 03 2017 at 17:07

The value of "this" depends on the "context" in which the function is executed. The context can be any object or the global object, i.e., window.

So the Semantic of "this" is different from the traditional OOP languages. And it causes problems: 1. when a function is passed to another variable (most likely, a callback); and 2. when a closure is invoked from a member method of a class.

In both cases, this is set to window.

4 SimonGroenewolt Jun 27 2010 at 20:15

Whould this help? (Most confusion of 'this' in javascript is coming from the fact that it generally is not linked to your object, but to the current executing scope -- that might not be exactly how it works but is always feels like that to me -- see the article for a complete explanation)

3 unclexo Jul 25 2018 at 14:04

A little bit info about this keyword

Let's log this keyword to the console in global scope without any more code but

console.log(this)

In Client/Browser this keyword is a global object which is window

console.log(this === window) // true

and

In Server/Node/Javascript runtime this keyword is also a global object which is module.exports

console.log(this === module.exports) // true
console.log(this === exports) // true

Keep in mind exports is just a reference to module.exports

1 PRADEEPSINGHChundawat Apr 06 2016 at 14:15

this use for Scope just like this

  <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>

value of txt1 and txt is same in Above example $(this)=$('#tbleName tbody tr') is Same

1 gman Jan 29 2019 at 01:37

I have a different take on this from the other answers that I hope is helpful.

One way to look at JavaScript is to see that there are only 1 way to call a function1. It is

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

There is always some value supplied for objectForThis.

Everything else is syntactic sugar for functionObject.call

So, everything else can be described by how it translates into functionObject.call.

If you just call a function then this is the "global object" which in the browser is the window

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

foo();  // this is the window object

In other words,

foo();

was effectively translated into

foo.call(window);

Note that if you use strict mode then this will be undefined

'use strict';

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

foo();  // this is the window object

which means

In other words,

foo();

was effectively translated into

foo.call(undefined);

In JavaScript there are operators like + and - and *. There is also the dot operator which is .

The . operator when used with a function on the right and an object on the left effectively means "pass object as this to function.

Example

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

bar.foo();  // this is bar

In other words bar.foo() translates into const temp = bar.foo; temp.call(bar);

Note that it doesn't matter how the function was created (mostly...). All of these will produce the same results

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

Again these all are just syntactic sugar for

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

One other wrinkle is the prototype chain. When you use a.b JavaScript first looks on the object referenced directly by a for the property b. If b is not found on the object then JavaScript will look in the object's prototype to find b.

There are various ways to define an object's prototype, the most common in 2019 is the class keyword. For the purposes of this though it doesn't matter. What matters is that as it looks in object a for property b if it finds property b on the object or in it's prototype chain if b ends up being a function then the same rules as above apply. The function b references will be called using the call method and passing a as objectForThis as shown a the top of this answer.

Now. Let's imagine we make a function that explicitly sets this before calling another function and then call it with the . (dot) operator

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

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

const obj = {
  bar,
};

obj.bar();  

Following the translation to use call, obj.bar() becomes const temp = obj.bar; temp.call(obj);. When we enter the bar function we call foo but we explicitly passed in another object for objectForThis so when we arrive at foo this is that inner object.

This is what both bind and => functions effectively do. They are more syntactic sugar. They effectively build a new invisible function exactly like bar above that explicitly sets this before it calls whatever function is specified. In the case of bind this is set to whatever you pass to 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'});

Note that if functionObject.bind did not exist we could make our own like this

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

and then we could call it like this

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

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

Arrow functions, the => operator are syntactic sugar for bind

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

is the same as

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

Just like bind, a new invisible function is created that calls the given function with a bound value for objectForThis but unlike bind the object to be bound is implicit. It's whatever this happens to be when the => operator is used.

So, just like the rules above

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() translates to const temp = obj.foo; temp.call(obj); which means the arrow operator inside foo will bind obj to a new invisible function and return that new invisible function which is assigned to b. b() will work as it always has as b.call(window) or b.call(undefined) calling the new invisible function that foo created. That invisible function ignores the this passed into it and passes obj as objectForThis` to the arrow function.

The code above translates to

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 is another function similar to call

functionName.apply(objectForThis, arrayOfArgs);

But as of ES6 conceptually you can even translate that into

functionName.call(objectForThis, ...arrayOfArgs);
WillemvanderVeen Aug 22 2018 at 00:12

Summary this Javascript:

  • The value of this is determined by how the function is invoked not, where it was created!
  • Usually the value of this is determined by the Object which is left of the dot. (window in global space)
  • In event listeners the value of this refers to the DOM element on which the event was called.
  • When in function is called with the new keyword the value of this refers to the newly created object
  • You can manipulate the value of this with the functions: call, apply, bind

Example:

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
              
             

Example event listeners:

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>

Example constructor:

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.

Lord May 20 2020 at 16:43

To understand "this" properly one must understand the context and scope and difference between them.

Scope: In javascript scope is related to the visibility of the variables, scope achieves through the use of the function. (Read more about scope)

Context: Context is related to objects. It refers to the object to which a function belongs. When you use the JavaScript “this” keyword, it refers to the object to which function belongs. For example, inside of a function, when you say: “this.accoutNumber”, you are referring to the property “accoutNumber”, that belongs to the object to which that function belongs.

If the object “myObj” has a method called “getMyName”, when the JavaScript keyword “this” is used inside of “getMyName”, it refers to “myObj”. If the function “getMyName” were executed in the global scope, then “this” refers to the window object (except in strict mode).

Now let's see some example:

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

Runnig abobve code in browser output will:

According to the output you are inside of the context of the window object, it is also visible that window prototype refers to the Object.

Now let's try inside of a function:

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

Output:

The output is the same because we logged 'this' variable in the global scope and we logged it in functional scope, we didn't change the context. In both case context was same, related to widow object.

Now let's create our own object. In javascript, you can create an object in many ways.

 <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>

Output:

So from the above example, we found that 'this' keyword is referring to a new context that is related to myObj, and myObject also has prototype chain to Object.

Let's go throw another example:

<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>

output: Make sense right? (read comments)

If you having trouble to understand the above example let's try with our own callback;

<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>

output:

Now let's Understand Scope, Self, IIFE and THIS how behaves

       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> 

Output is pretty awesome right?