362

I saw the following in the source for WebKit HTML 5 SQL Storage Notes Demo:

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

The author uses self in some places (the function body) and this in other places (the bodies of functions defined in the argument list of methods). What's going on? Now that I've noticed it once, will I start seeing it everywhere?

DanMan
  • 10,431
  • 3
  • 36
  • 57
Thomas L Holaday
  • 13,068
  • 5
  • 38
  • 50
  • 5
    This is a JS language feature called “lexical closure." – subZero Dec 07 '13 at 12:07
  • 2
    Possible duplicate of: [var self = this?](http://stackoverflow.com/q/337878/1497596). – DavidRR Jun 17 '15 at 15:35
  • the concept of THIS is explained explicitly here https://scotch.io/@alZami/understanding-this-in-javascript – AL-zami Sep 10 '17 at 19:10
  • Relevant example in this answer https://stackoverflow.com/a/20279485/5610569 (to the question "How to access the correct `this` inside a callback?") – FluxLemur Jun 18 '18 at 21:40

10 Answers10

436

See this article on alistapart.com. (Ed: The article has been updated since originally linked)

self is being used to maintain a reference to the original this even as the context is changing. It's a technique often used in event handlers (especially in closures).

Edit: Note that using self is now discouraged as window.self exists and has the potential to cause errors if you are not careful.

What you call the variable doesn't particularly matter. var that = this; is fine, but there's nothing magic about the name.

Functions declared inside a context (e.g. callbacks, closures) will have access to the variables/function declared in the same scope or above.

For example, a simple event callback:

function MyConstructor(options) {
  let that = this;

  this.someprop = options.someprop || 'defaultprop';

  document.addEventListener('click', (event) => {
    alert(that.someprop);
  });
}

new MyConstructor({
  someprop: "Hello World"
});
Jonathan Fingland
  • 53,185
  • 11
  • 81
  • 77
98

I think the variable name 'self' should not be used this way anymore, since modern browsers provide a global variable self pointing to the global object of either a normal window or a WebWorker.

To avoid confusion and potential conflicts, you can write var thiz = this or var that = this instead.

Étienne
  • 4,131
  • 2
  • 27
  • 49
Duan Yao
  • 1,309
  • 10
  • 12
  • 44
    I usually use `_this` – djheru Mar 20 '14 at 19:48
  • 6
    @djheru +1. so much nicer than "`that`" (which my brain will never get used to). – o_o_o-- Jul 19 '14 at 23:29
  • 9
    I started using "me" :) – Mopparthy Ravindranath Jun 27 '15 at 17:15
  • 3
    Until modern browsers start providing a global variable _this, that, or me. – Beejor Jul 03 '15 at 02:34
  • 10
    There's absolutely no problem with using the name `self` as long as you declare it as a `var`iable, it'll shadow the global. Of course if you forgot the `var` then it wouldn't work with any other name either. – Bergi Aug 16 '15 at 18:58
  • 1
    @Bergi - One problem is that eslint won't catch it as an error if you forget to declare 'var self = this'. – aaaaaa Apr 12 '16 at 22:50
  • @aaaaaa It does not? Have you declared `self` as an implicit global to eslint somewhere? – Bergi Apr 12 '16 at 23:15
  • @Bergi Nope - it's implied via the browser environment: "env": { "browser": true } – aaaaaa Apr 12 '16 at 23:58
  • 1
    @Matian2040 Existing codes which use `var self = this` continue to work, because the global `self` is shadowed, as @Bergi said. However If someone tries to modify existing code without carefully check existing uses of `self` in the same scope, he/she may unintentionally shadow the global `self` and breaks the code. That's why `var self = this` should be avoided. – Duan Yao Jul 19 '16 at 02:00
  • @djheru I agree with the concept of _this to annotate top level this, and for me if the scope gets even deeper prepending additional "_" would work for me. `__this = this;` or it can be any prefix (except for $) :D – jatazoulja Jan 17 '17 at 12:29
  • `they` is fashionably [singular](https://en.wikipedia.org/wiki/Singular_they). The animate variant of `this`. – Bob Stein Oct 26 '19 at 15:52
35

Yes, you'll see it everywhere. It's often that = this;.

See how self is used inside functions called by events? Those would have their own context, so self is used to hold the this that came into Note().

The reason self is still available to the functions, even though they can only execute after the Note() function has finished executing, is that inner functions get the context of the outer function due to closure.

Stacked
  • 5,676
  • 5
  • 52
  • 69
Nosredna
  • 74,873
  • 15
  • 91
  • 122
  • 12
    For me the cogent point is that `self` has no special meaning. I personally prefer using a var named something other than `self` since it frequently confuses me, as I expect 'self' to be a reserved word. So I like your answer. And in the example of the OP, I'd prefer `var thisNote = this` or similar. – steve Jan 07 '14 at 08:16
  • @steve agreed, although I try to avoid using this/self references in general as they are very brittle in terms of maintainability. – mattLummus Mar 08 '15 at 00:02
28

It should also be noted there is an alternative Proxy pattern for maintaining a reference to the original this in a callback if you dislike the var self = this idiom.

As a function can be called with a given context by using function.apply or function.call, you can write a wrapper that returns a function that calls your function with apply or call using the given context. See jQuery's proxy function for an implementation of this pattern. Here is an example of using it:

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFunc can then be called and will have your version of this as the context.

Max
  • 6,331
  • 5
  • 41
  • 58
19

As others have explained, var self = this; allows code in a closure to refer back to the parent scope.

However, it's now 2018 and ES6 is widely supported by all major web browsers. The var self = this; idiom isn't quite as essential as it once was.

It's now possible to avoid var self = this; through the use of arrow functions.

In instances where we would have used var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

We can now use an arrow function without var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

Arrow functions do not have their own this and simply assume the enclosing scope.

Elliot B.
  • 14,589
  • 9
  • 70
  • 99
  • Or – shock, horror! – why not pass the actual relevant thing as an argument to your function (closure)? Why the hell are you referencing out of scope state, why the hell is anyone programming like this? There is _never_ any real reason to do this. Instead `.addEventListender("click", (x) => { console.log(x); });` You've explained the how and why very clearly, and I agree using arrow functions makes more sense, but still... this is just terrible, lazy, messy, programming. – Benjamin R Aug 10 '18 at 12:07
  • 4
    In JavaScript, referring back to the parent scope is extremely common and necessary. It's a fundamental part of the language. Your suggestion to pass in the parent scope as an argument on the event handler isn't actually possible. Also, in ES6, arrow functions use lexical scoping — 'this' refers to it's current surrounding scope and no further -- it's not "referencing out of scope state" or anything like that. – Elliot B. Aug 10 '18 at 18:29
9

It's a JavaScript quirk. When a function is a property of an object, more aptly called a method, this refers to the object. In the example of an event handler, the containing object is the element that triggered the event. When a standard function is invoked, this will refer to the global object. When you have nested functions as in your example, this does not relate to the context of the outer function at all. Inner functions do share scope with the containing function, so developers will use variations of var that = this in order to preserve the this they need in the inner function.

kombat
  • 313
  • 5
  • 15
9

The variable is captured by the inline functions defined in the method. this in the function will refer to another object. This way, you can make the function hold a reference to the this in the outer scope.

mmx
  • 390,062
  • 84
  • 829
  • 778
5

Actually self is a reference to window (window.self) therefore when you say var self = 'something' you override a window reference to itself - because self exist in window object.

This is why most developers prefer var that = this over var self = this;

Anyway; var that = this; is not in line with the good practice ... presuming that your code will be revised / modified later by other developers you should use the most common programming standards in respect with developer community

Therefore you should use something like var oldThis / var oThis / etc - to be clear in your scope // ..is not that much but will save few seconds and few brain cycles

miphe
  • 1,306
  • 13
  • 28
SorinN
  • 164
  • 2
  • 5
0

As mentioned several times above, 'self' is simply being used to keep a reference to 'this' prior to entering the funcition. Once in the function 'this' refers to something else.

Cyprien
  • 21
  • 1
  • @JohnPaul ... this _does_ provide an answer. It might not be the right answer, but how can you say that "it is being used to ... " is not an answer to "why did he do this"? – GreenAsJade Jan 02 '15 at 23:31
-3
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call(thatt);