Difference between this and self in JavaScript

Unless set elsewhere, the value of self is window because JavaScript lets you access any property x of window as simply x, instead of window.x. Therefore, self is really window.self, which is different to this.

window.self === window; // true

If you're using a function that is executed in the global scope and is not in strict mode, this defaults to window, and therefore

function foo() {
    console.log(
        window.self === window, // is self window?
        window.self === this,   // is self this?
        this === window         // is this window?
    );
}
foo(); // true true true

If you're using a function in a different context, this will refer to that context, but self will still be window.

// invoke foo with context {}
foo.call({}); // true false false

You can find window.self defined in the W3C 2006 working draft for the Window Object here.


A slight addition to this as people may encounter this in the context of service workers, in which case it means something slightly different.

You might see this in a service worker module:

self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
});

Here self refers to the WorkerGlobalScope, and this is the standard method for setting event listeners.

From Mozilla docs:

By using self, you can refer to the global scope in a way that will work not only in a window context (self will resolve to window.self) but also in a worker context (self will then resolve to WorkerGlobalScope.self).


The reference to ECMA 5 needs clarifying.

I assume it means ECMA-262 Edition 5. It should be noted that ECMA-262 (a.k.a. ECMAScript or, less accurately, Javascript) is a general scripting language which has been implemented in Internet Browsers. From the Edition 5.1 standard:

The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList:

  1. If the function code is strict code, set the ThisBinding to thisArg.
  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.
  3. Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
  4. Else set the ThisBinding to thisArg
  5. ... (not about "this")

The term "global object" refers to whatever object is at the top of the scope chain. For browsers this would be the "window" object but this is an implementation choice (Windows Script Host has an invisible global object but no strict mode so unqualified references access its properties and there is no global "self"). Also, "strict mode" must be explicitly enabled otherwise it is not active (section 14.1 of the standard). As such, an undefined "this" would still resolve to the global object (window) in "ECMA 5" with strict mode not active.

So the answer to the question is:

"this" always refers to the object invoking the function. If the function was not invoked by an object (i.e. not a method call) then "this" (as passed to the function) is "undefined". However, if NOT using strict mode then an undefined "this" is set to the global object (rule 2 above).

"self" has no special syntactic meaning, it is just an identifier. Browsers tend to define window.self (just a property of the global window object) = window. This results in unqualified references to "self" being the same as "window" UNLESS "self" has been redefined within an enclosing scope (such as by "var self = this;" above. Good luck redefining "this".)

So the full explanation of the example above is:

outer func:  this.foo = bar
// "this" refers to the invoking object "myObject"
outer func:  self.foo = bar
// "self" resolves to the variable in the local scope which has been set to "this" so it is also "myObject"
inner func:  this.foo = undefined
// "this" refers to the invoking object (none) and so is replaced by the global object (strict mode must be off). "window" has no foo property so its "value" is undefined.
inner func:  self.foo = bar
// self resolves to the variable in the enclosing scope which is still "myObject"

An interesting variation of the example creates a closure by returning a reference to the inner function.

var myObject = {
 foo: "bar",
 func: function() {
    var self = this;
    console.log("outer func:  this.foo = " + this.foo);
    console.log("outer func:  self.foo = " + self.foo);
    return function() {
        console.log("inner func:  this.foo = " + this.foo);
        console.log("inner func:  self.foo = " + self.foo);
    };
  }
};
var yourObject = {
 foo: "blat",
 func: myObject.func() // function call not function object
};
console.log("----");
yourObject.func();

Producing

outer func:  this.foo = bar
outer func:  self.foo = bar
----
inner func:  this.foo = blat
inner func:  self.foo = bar

Note how the inner function is not called until invoked by yourObject. So this.foo is now yourObject.foo but self still resolves to the variable in the enclosing scope which, at the time the inner function object was returned, was (and in the resulting closure still is) myObject. So, within the inner function, "this" refers to the object calling the inner function while "self" refers to the object which called the outer function to create the reference to the inner function.

To summarize the summary of the summary, "this" is defined by the language standard, "self" is defined by whoever defines it (runtime implementer or end programmer).


Although I am late here but I came across one example which too can be helpful to understand this further:

var myObject = {
 foo: "bar",
 func: function() {
    var self = this;
    console.log("outer func:  this.foo = " + this.foo);
    console.log("outer func:  self.foo = " + self.foo);
    (function() {
        console.log("inner func:  this.foo = " + this.foo);
        console.log("inner func:  self.foo = " + self.foo);
    }());
  }
};
myObject.func();

O/P

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar

Prior to ECMA 5, this in the inner function would refer to the global window object; whereas, as of ECMA 5, this in the inner function would be undefined.

Tags:

Javascript