371

In a JavaScript file I saw:

function Somefunction(){
   var that = this; 
   ... 
}

What is the purpose of declaring that and assigning this this to it?

El Ronnoco
  • 11,001
  • 5
  • 34
  • 63
Chris
  • 11,100
  • 13
  • 44
  • 67
  • 3
    possible duplicate of [var self = this?](http://stackoverflow.com/q/337878/1048572) – Bergi Jan 14 '15 at 02:45
  • 7
    The "this" and "that" hack is not required for arrow functions. With arrow functions "this" works as expected. See here for more details [ES6 In Depth: Arrow functions](https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/) – satguru srivastava Apr 26 '17 at 19:12
  • 1
    here concept of this is explained https://scotch.io/@alZami/understanding-this-in-javascript – AL-zami Sep 11 '17 at 05:20
  • A great explanation on mysterious this behavior based on context [here](https://zellwk.com/blog/this/) – RBT Oct 23 '17 at 10:58
  • 1
    Latest & updated explanation can be found [here](https://medium.com/@VoyagerSukrit/var-me-this-in-javascript-65fee9d7a8f8) – Sukrit Gupta May 10 '19 at 13:32

6 Answers6

503

I'm going to begin this answer with an illustration:

var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
    // this is a reference to the element clicked on

    var that = this;

    colours.forEach(function() {
        // this is undefined
        // that is a reference to the element clicked on
    });
});

My answer originally demonstrated this with jQuery, which is only very slightly different:

$('#element').click(function(){
    // this is a reference to the element clicked on

    var that = this;

    $('.elements').each(function(){
        // this is a reference to the current element in the loop
        // that is still a reference to the element clicked on
    });
});

Because this frequently changes when you change the scope by calling a new function, you can't access the original value by using it. Aliasing it to that allows you still to access the original value of this.

Personally, I dislike the use of that as the alias. It is rarely obvious what it is referring to, especially if the functions are longer than a couple of lines. I always use a more descriptive alias. In my examples above, I'd probably use clickedEl.

lonesomeday
  • 215,182
  • 48
  • 300
  • 305
  • 156
    I usually go with `var self = this;`. The word `that` seems to imply the variable is anything BUT `this`. – David Murdoch Feb 03 '11 at 14:34
  • 13
    @David Yes I've thought **that** is somewhat misleading. But if, as Crockford says, it's a convention, is it wise to go down that route. I totally agree with you though, makes much more sense. – El Ronnoco Feb 03 '11 at 14:59
  • @David: These were my thoughts, var that = this and I am wondering what is that? If implementation used self, I probably would not have even wondered. – Chris Feb 03 '11 at 15:07
  • 5
    @El Ronnoco, but "He's got gray hair and a scraggly beard and his manner brings to mind a grumpy old man who yells at kids to get off of his lawn." - http://blogging.compendiumblog.com/blog/software-for-humans/0/0/on-becoming-a-douglas-crockford-fanboy ;-p – David Murdoch Feb 03 '11 at 20:30
  • I was just watching [this video](http://blog.mozilla.com/dherman/2011/02/23/my-js-meetup-talk/) on EcmaScript.next and the presenter, dherman from Mozilla, refers to javascript's `this` scoping issue as "the `var self = this;` trick". Interestingly, with the new function literal syntax `this` will be lexically bound; e.g., `function Node(){ var self = this; this.children.forEach(#(child){ console.log(this === self); /* true! */ });}` where `#` is the new syntax. – David Murdoch Feb 24 '11 at 13:43
  • So in this new function literal syntax how would you get the this for the child? – Razor Storm Apr 10 '12 at 03:36
  • 1
    I'd use something like `clickedEl`, too. – Lightness Races in Orbit Jan 18 '13 at 00:19
  • 7
    @ElRonnoco: That's an appeal to authority, though. If we only ever do what "the famous people" say we should do, we're headed for disaster. – Lightness Races in Orbit Jan 18 '13 at 00:19
  • @LightnessRacesinOrbit Well I wouldn't describe crockford as famous! I'm not proposing we take Kim Kardashian's advice on JavaScript conventions. However Crockford does know what he's talking about when it comes to JS. He certainly outranks me, I can't speak on anyone else behalf. And his website could certainly use an update, it's bloody awful! :) – El Ronnoco Jan 18 '13 at 10:33
  • @DavidMurdoch Once caveat to using `self` is that in most browser implementations, [`window.self`](https://developer.mozilla.org/en-US/docs/Web/API/window.self) is an environment-set global variable. Shadowing `self` with a local variable might break third-party scripts that expect to have global access to the browser-set `self` attribute of `window`. In practice, of course, this is rarely a problem. – apsillers May 28 '13 at 14:33
  • 1
    @apsillers, that is just not true. It could only happen if you were inlining the 3rd party script directly within the function that assigns `self` to `this`; at which point it is no longer third party - you have complete control over the code. – David Murdoch May 28 '13 at 17:19
  • 1
    @DavidMurdoch Agreed -- it wouldn't be a problem with any sensible plugin architecture. It would be better to say that shadowing of `self` could be (theoretically) problematic if you're maintaining some extant code you didn't write. A full discussion of whether or not my concern is valid as a legitimate "best practice" lies in the scope of Programmers.SE, so I won't try to fully justify it here; rather, I'll simply let it stand as an extant concern with admittedly remote probability. – apsillers May 28 '13 at 17:29
  • I dislike the choice to use jQuery for the example. A simple Array.forEach sample would show the problem all the same and not involve any libraries. – Jasper Jul 10 '14 at 11:02
  • @Jasper Indeed. I would have do that if i were writing the answer today, and in fact I'll add it to the answer. In 2011 `Array.forEach` was not in widespread use. – lonesomeday Jul 10 '14 at 11:04
  • Ah yes, I do remember when you had to add that function to the array prototype for browser compatibility. – Jasper Jul 10 '14 at 12:40
  • 4
    The `forEach` function takes a second optional argument is which is the binding of the function. `colours.forEach(function(){/* 'this' is bound correctly --> */}, this);` So a note should be added that `var that = this` isn't _actually_ needed with `forEach`. – Matt Clarkson Apr 08 '15 at 12:29
  • In the first foreach 'this' is undefined, and in the second one its not. Why? – user5539357 Jun 24 '16 at 11:05
  • 1
    @user5539357 Because that's how forEach works. That's simply how the language specification defines it. My guess is that this was done to avoid ambiguity/confusion. – lonesomeday Jun 27 '16 at 11:50
110

From Crockford

By convention, we make a private that variable. This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.

JS Fiddle

function usesThis(name) {
    this.myName = name;

    function returnMe() {
        return this;        //scope is lost because of the inner function
    }

    return {
        returnMe : returnMe
    }
}

function usesThat(name) {
    var that = this;
    this.myName = name;

    function returnMe() {
        return that;            //scope is baked in with 'that' to the "class"
    }

    return {
        returnMe : returnMe
    }
}

var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' +
      "UsesThis thinks it's called " + usesthis.returnMe().myName);

This alerts...

UsesThat thinks it's called Dave

UsesThis thinks it's called undefined

El Ronnoco
  • 11,001
  • 5
  • 34
  • 63
  • 2
    Thanks, sums it up well enough for me. – Chris Feb 03 '11 at 13:25
  • 3
    I read that, did not understand because it had no detail, searched on Google, found this page. Where I am again pointed to the same sentence. Hence the downvote. – Aditya M P Feb 21 '13 at 07:19
  • 3
    That's a fair point, I would say that someone unfamiliar with JavaScript would have difficulty grasping the concept from my answer alone. I did answer very briefly (and I did link to the page you Googled for..) I'd say lonesomeday's answer is the clearest, though I would still have preferred it in plain JS as opposed to a jQuery example. – El Ronnoco Feb 21 '13 at 09:48
  • :) I am glad you took no offence. Here's a cookie, please have a nice day good sir! – Aditya M P Feb 21 '13 at 12:56
  • 17
    I take no offence. It's nice to see someone who comments when downvoting! – El Ronnoco Feb 21 '13 at 16:43
  • 4
    The problem with Crockford's answer is the `that` variable isn't used in his example at all. It makes it look as though just creating a variable holding `this` does something to the rest of the code. – r3m0t Jul 03 '13 at 17:27
  • 1
    I never realised that needing to do this was down to an error in the spec! I mean, it's a bit annoying to need to do it but I thought there would be a real reason. – Matthew Jun 19 '14 at 16:58
  • I **always** thought that `this` not working in private functions was intended behaviour. If this "bug" was fixed and still worked as expected, it'd make a lot of code more readable and a lot of coders happy. – bryc Aug 20 '14 at 14:44
  • @r3m0t, so using "that" wasn't made to be taken literally? – eflat Mar 28 '15 at 19:08
  • @eflat no, it's a misnomer really. I think it may have been adopted because it is a similar looking word (4 chars, starts with t) - but of course from an English perspective *this* is considered separate from *that*, rather than synonymous. I use **self**, I think this may be becoming more common now. – El Ronnoco Apr 08 '15 at 13:04
88

This is a hack to make inner functions (functions defined inside other functions) work more like they should. In javascript when you define one function inside another this automatically gets set to the global scope. This can be confusing because you expect this to have the same value as in the outer function.

var car = {};
car.starter = {};

car.start = function(){
    var that = this;

    // you can access car.starter inside this method with 'this'
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to the global scope
        // 'this.starter' is undefined, so we use 'that' instead.
        that.starter.active = true;

        // you could also use car.starter, but using 'that' gives
        // us more consistency and flexibility
    };

    activateStarter();

};

This is specifically a problem when you create a function as a method of an object (like car.start in the example) then create a function inside that method (like activateStarter). In the top level method this points to the object it is a method of (in this case, car) but in the inner function this now points to the global scope. This is a pain.

Creating a variable to use by convention in both scopes is a solution for this very general problem with javascript (though it's useful in jquery functions, too). This is why the very general sounding name that is used. It's an easily recognizable convention for overcoming a shortcoming in the language.

Like El Ronnoco hints at Douglas Crockford thinks this is a good idea.

Waylon Flinn
  • 18,635
  • 12
  • 65
  • 70
  • 8
    I suppose this is more useful answer than accepted one. Because it clarifies the reason why Crockford has invented "that" while answer about jQuery doesn't. – Konstantin Smolyanin Jul 17 '13 at 14:20
  • 5
    This is actually a better example then the accepted answer. It explains what it's like as a "an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions" said by Douglas. – kakacii Jul 22 '13 at 13:10
  • 1
    You may want to make it grammar correct though. I know it's more like a typo, but it could confuse javascript beginners as this question is more beginner like. I mean it should be: var car = {}; car.starter = {};car.start = function(){...} – kakacii Jul 22 '13 at 13:12
  • 1
    @kakacii Thanks. Fixed now. – Waylon Flinn Oct 30 '13 at 15:17
10

The use of that is not really necessary if you make a workaround with the use of call() or apply():

var car = {};
car.starter = {};

car.start = function(){
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to our main object
        this.starter.active = true;
    };

    activateStarter.apply(this);
};
Adela
  • 101
  • 1
  • 2
3

Sometimes this can refer to another scope and refer to something else, for example suppose you want to call a constructor method inside a DOM event, in this case this will refer to the DOM element not the created object.

HTML

<button id="button">Alert Name</button>

JS

var Person = function(name) {
  this.name = name;
  var that = this;
  this.sayHi = function() {
    alert(that.name);
  };
};

var ahmad = new Person('Ahmad');
var element = document.getElementById('button');
element.addEventListener('click', ahmad.sayHi); // => Ahmad

Demo

The solution above will assing this to that then we can and access the name property inside the sayHi method from that, so this can be called without issues inside the DOM call.

Another solution is to assign an empty that object and add properties and methods to it and then return it. But with this solution you lost the prototype of the constructor.

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};
Ahmad Ajmi
  • 5,905
  • 3
  • 29
  • 51
2

Here is an example `

$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();

            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                    var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'. 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

So you can see that value of this is two different values depending on the DOM element you target but when you add "that" to the code above you change the value of "this" you are targeting.

`$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();
            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                var that = this;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                   ***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a"....
                    var imgAlt = $(this).find('img').attr('alt'); 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

.....$(that).css("background-color", "#ffe700"); //Here value of "that" is ".our-work-group > p > a" because the value of var that = this; so even though we are at "this"= '.our-work-single-page', still we can use "that" to manipulate previous DOM element.