5

Is there a particular reason why i often encounter:

(function() {
  console.log("Hello");
}).call(this);

instead of:

(function() {
  console.log("Hello");
})();

It should have the same effect when passing this to call or not?

There seems to be some performance difference: http://jsperf.com/call-vs-parenthesis.

Nick Russler
  • 4,608
  • 6
  • 51
  • 88

2 Answers2

7

Presumably the code within that function uses this (where you just have console.log). In the version with call, this within the function is the same as this outside it. Without call, this inside the function is either the global object (loose mode) or undefined (strict mode).

If you're not using this within the function, there's no reason to be doing the call version, and I would lean toward not doing so because it's additional unnecessary complexity (and apparently a very very small performance cost).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • So they behave the same way in loose mode but not in strict mode? – Nick Russler Dec 10 '13 at 18:49
  • @NickRussler: Only if that code is at global scope (or was otherwise called with `this` being the global object). I assumed it wasn't, that it was in code where `this` *wasn't* the global object (DOM event handlers, etc.). – T.J. Crowder Dec 10 '13 at 18:49
  • 1
    @Nick - no, assume that the code OUTSIDE of your IIFE has `this` set to something other than the global object – Adam Rackis Dec 10 '13 at 18:49
  • Ahh sure, now i got it. Thank you both. AFAIK CoffeeScript compiles files into an anoynmous function that is executed with call, which got me wondering.. – Nick Russler Dec 10 '13 at 18:51
  • Source for the performance cost? Just want to see if there truly is a performance cost, or if this is just conjecture. – codefactor Dec 10 '13 at 18:56
  • @codefactor: See the jsperf link in the question. – T.J. Crowder Dec 10 '13 at 18:56
  • I wonder if that jsperf is accurate (not many actual tests ran so far) - I was under the impression that adding a `.call` would not negatively impact performance, and vaguely remembering somewhere that a normal function call is interpreted the same way as `.call` under the covers. – codefactor Dec 10 '13 at 19:01
  • @codefactor: There's overhead that can't be done away with, so the two can never be *exactly* the same. The engine is required to resolve the `call` property, if nothing else, which is a non-zero-time operation. (Think it can shortcut it? Nope. Consider: http://jsbin.com/eyohUNEY/1/edit) But again, we're talking **very very small**, any additional overhead is almost certain to be washed out by what the function you're calling actually does. – T.J. Crowder Dec 10 '13 at 19:15
3

The addition of .call(this) is important, it changes the context of the function enclosure, meaning that the this keyword will refer to the same this as the outer function enclosure.

In your particular code it doesn't make any difference because inside your function you do not refer to this at all.

this.a = 123;
(function() {
   console.log(this.a); // always 123 regardless of scope
}).call(this);

That is significant assuming that this refers to something other than the window object. If this is already pointing to the window, then adding .call(this) makes no difference, since without it, by default the this will go to the window.

codefactor
  • 1,616
  • 2
  • 18
  • 41