Let's disassemble this piece of code.
First off there is an anonymous function with immediate invocation. It's similar to this:
(function () {/**/}).call();
(new Date()).getTime(); // timestamp since 1970 jan 1 in milliseconds
We don't assign new Date()
to a variable, instead we use it immediately.
Now why use .call
instead of just ()
?
.call
is a method all Functions
have. The first argument is what this
will be bound to, subsequent arguments will be passed as arguments to the function. So:
(function () {
console.log(this.foo); // bar
}).call({ "foo": "bar" });
This works in conjunction with undefined
(see below).
.call
is the same as .apply
with one minor difference. .apply
only takes 2 arguments, where the 2nd is an array of arguments. This would be similar:
(function () {}).call(this, "foo", "bar");
(function () {}).apply(this, [ "foo", "bar" ]);
A common use of apply is in conjunction with the magic variable arguments
.
(function () {
console.log(Array.prototype.slice.call(arguments, 1)); // [ "bar" ]
})([ "foo", "bar" ]);
Array.prototype.slice.call(arguments, 1)
may look scary but really it's just arguments.slice(1)
, but arguments
isn't an Array
so it doesn't have a slice
function. We borrow Array
s slice
function and use .call
to set the this
to arguments
. Array.prototype.slice(arguments, 1??)
is incorrect.
Now why is there this
in .call(this)
? this
always points to the context you're in. If you're in an instance of a class it will point to the instance and if you're in the global scope it will point to that. In a browser environment it is also window
.
Why undefined
? Since we did a .call(this)
with no second argument, all arguments to our anonymous function are undefined
. I'm not really sure why you need to make an explicit variable named undefined
there. Maybe this is support for some browsers or some lint tool that likes to see undefined
defined.
Thanks to @TedHopp. undefined
is fickle.
var undefined = "foo";
console.log(undefined); // undefined
(function (undefined) {
console.log(undefined); // "foo"
})("foo");
You can just as easily have:
(function () {
/* code here */
}());
This is completely valid and works just the same. There might be some performance or linting benefits to use the form you posted.