98

Why is this in an anonymous function undefined when using javascript in strict mode? I understand why this could make sense, but I couldn't find any concrete answer.

Example:

(function () {
    "use strict";

    this.foo = "bar"; // *this* is undefined, why?
}());

Test in a fiddle: http://jsfiddle.net/Pyr5g/1/ Check out the logger (firebug).

T. Junghans
  • 11,385
  • 7
  • 52
  • 75
  • 4
    Note that this has nothing to do with anonymous functions, but the invocation method. See [this modified fiddle](http://jsfiddle.net/Pyr5g/3/) (look in the console log). – Phrogz Mar 22 '12 at 13:05
  • @Phrogz: This may be where some of the confusion came from. Thanks for pointing that out. – T. Junghans Mar 22 '12 at 13:10

4 Answers4

114

It's because, until ECMAscript 262 edition 5, there was a big confusion if people who where using the constructor pattern, forgot to use the new keyword. If you forgot to use new when calling a constructor function in ES3, this referenced the global object (window in a browser) and you would clobber the global object with variables.

That was terrible behavior and so people at ECMA decided, just to set this to undefined.

Example:

function myConstructor() {
    this.a = 'foo';
    this.b = 'bar';
}

myInstance     = new myConstructor(); // all cool, all fine. a and b were created in a new local object
myBadInstance  = myConstructor(); // oh my gosh, we just created a, and b on the window object

The last line would throw an error in ES5 strict

"TypeError: this is undefined"

(which is a much better behavior)

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • 4
    This makes sense. Do you have a reference to back up the statement? – Rob W Mar 22 '12 at 12:51
  • 1
    @RobW: I would have to search myself, But I heard Douglas Crockford several times where he said, this was the reason for that decision. – jAndy Mar 22 '12 at 12:54
  • 1
    It is mentioned in JavaScript: The Good Parts by Crockford. It is described in detail. Not about ECMAs decision, though. – madr Mar 22 '12 at 12:59
  • @madr: I don't think you got the point. Crockford is also part of the committee btw. – jAndy Mar 22 '12 at 13:00
  • 1
    This is the logical reason for why strict mode defaults this to undefined. The other logical reason is efficiency, the other logical reason is that `this === window` is confusing and leaks global scope as a token into functions – Raynos Mar 22 '12 at 13:03
  • 2
    @jAndy: Thanks for the answer. This makes sense. I also found a compact explanation of the changes to **this** on http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/: "Most notably, if the first argument to call or apply is null or undefined, the this value of the invoked function will not be converted to the global object." – T. Junghans Mar 22 '12 at 13:07
  • @jAndy: it was a response to Rob W, sorry. – madr Mar 22 '12 at 13:12
  • 1
    Oh my god.. I've been debugging my nodejs app for almost two hours, and couldn't find what went wrong. Found this question, read your answer, and at the **"forgot to use the `new` keyword"** part, I've experienced my own *facepalm of the month* moment. – frzsombor Apr 27 '19 at 18:33
15

There is a mechanism called "boxing" which wraps or change the this object before entering the context of the called function. In your case, the value of this should be undefined because you are not calling the function as a method of an object. If non strict mode, in this case, this is replaced by the window object. In strict mode it's always unchanged, that's why it's undefined here.

You can find more information at
https://developer.mozilla.org/en/JavaScript/Strict_mode

Phrogz
  • 296,393
  • 112
  • 651
  • 745
Samuel Rossille
  • 18,940
  • 18
  • 62
  • 90
13

According to This Stack Overflow answer, you can use this inside anonymous functions, simply by calling .call(this) at the end of it.

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);
Community
  • 1
  • 1
ReverseTales
  • 139
  • 1
  • 2
0

Strict mode does not allow default binding, so try this:

**yourFunctionName.bind(this)**

I hope now it's working fine.

Mohammad Rana
  • 29
  • 1
  • 3