60

I have seen JavaScript written like this (it was at a demonstration, and I don’t have the actual code at hand, but it was implied this was normal):

(function() {    

    var a = 1;

    this.sayA = function() {
        alert(a);
    }

}).call(this);

sayA();

I suppose it is written an an anonymous function so that the variable a is not globally available.

What could the point of the .call(this) be? Since this function was not nested, this was just the window. How does it differ from just writing () at the end?

Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
zod
  • 2,688
  • 5
  • 27
  • 49
  • 1
    There should be no difference. It might just be a matter of coding style, to make invocation more apparent. – Felix Kling Nov 07 '11 at 11:30
  • 3
    I think there is a difference. If the context is not the global scope, the anonymous function will act as a member function for whatever `this` might be. Would it not? – Yoshi Nov 07 '11 at 11:41

4 Answers4

35

Try this:

function Foo() {

  (function () {
    console.log(this);
    // > Foo
  }).call(this);

  (function () {
    console.log(this);
    // > undefined in strict mode, or Window in non strict mode
  })();
}

var bar = new Foo;

So, if for whatever reason you use this, it's a way to make the IIFE act as if it were a member function of Foo, specifically when creating instances of a user-defined object type.

steviesh
  • 1,740
  • 6
  • 19
  • 33
Yoshi
  • 54,081
  • 14
  • 89
  • 103
  • 3
    but how is that different from var bar = function (){console.log(this) x 2;} – user2167582 Jun 25 '13 at 19:03
  • Is there an ES2015 best practice for this? – Gus Mar 22 '16 at 17:40
  • @Gus: Use an arrow function for your IIFE if you want the same `this` as outside. Or just block scope only. – Bergi Aug 27 '16 at 12:18
  • I think some programmers must be simply overusing this technique in places where it doesn't make sense. For example: https://github.com/iabramo/brightcove-gtm/blob/master/dist/videojs.gtm.videocloud.js. – Matt Browne Mar 02 '17 at 21:21
34

I was curious about this as well as I had just seen John Resig's talk about this video. Yoshi had a great answer but I had to test it in a bit in console log to understand and I thought this modification to his answer might help some people who were having trouble at first like me:

function Foo() {
  this.foo = true;
  (function () {
      console.log("Foo = " + this.foo);
      // Outputs undefined
  }());
  (function () {
      console.log("Foo = " + this.foo);
      // Outputs true
  }).call(this);

  (function () {
      console.log(this);
      // Outputs undefined in strict mode, or Window in non strict mode
      // Anonymous functions usually default to the global scope
  })();
}

var bar = new Foo;

It just made a little more sense to me to see the first and second ones side by side, showing that .call(this) essentially gives you the ability to pass the current context to an anonymous function.

Thanks for the question and thanks Yoshi for the clear answer!

netpoetica
  • 3,375
  • 4
  • 27
  • 37
15

Since this function was not nested, this was just the window. How does it differ from just writing () at the end?

No - not in strict mode:

  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.

In strict mode, the this is just directly set to the given value, which is undefined for a normal call. Therefore, .call(this) is used to pass the global object explicitly in. You can try this in the console:

> (function() { "use strict"; console.log(this); })()
undefined
> (function() { "use strict"; console.log(this); }).call(this)
Window

It might not make a difference for sloppy code, but it's a good practise and future-compatible :-)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
15

this passed to the function sets the context of the execution, so inside your anonymous function this refers to the window.

You can than write this.alert('');.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • thanks for the recommendation. – zod Feb 03 '12 at 17:03
  • 1
    Could downvoter care to explain, please? – Jakub Konecki Sep 04 '12 at 08:27
  • 1
    @Jakub. I've downvoted your answer because of "Not a common practice/I wouldn't recommend" part. It is a common practice and it's often recommended one. See for example: http://stackoverflow.com/questions/4542942/why-use-the-javascript-function-wrapper-added-in-coffeescript-callthis – Łukasz Wiatrak Mar 03 '13 at 12:40