Reason behind this self invoking anonymous function variant
.call(this)
(was actually just ()
until I changed it) ensures your top level this
to be consistent through strict mode, --bare
option and/or the running environment (where top level this
doesn't point to global object).
Anonymous self-invoking function is automatically passed as an argument to above declared local function. Why?
Remove some newlines and you can see why:
let myfunc = function(a) {
return function localScope(b) {
console.log(a + b + " this")
}
}(function () {
console.log('test')
})()
And function(){}()
is actually valid syntax to call that anonymous function. You can use a defensive semicolon to properly split the statements:
let myfunc = function(a) {
return function localScope(b) {
console.log(a + b + " this")
}
};
(function () {
console.log('test')
})()
Not self invoking anonymous functions
"Q: Is that just preference you think?"
Yes, but using a unary !
operator, you can avoid a few bugs when you forget a semicolon before the IIFE, which can cause the ()
to be interpreted as a function call.
alert('foo') // alerts 'foo'
(function() { // TypeError: undefined is not a function
alert('bar');
})()
Here the outer ()
is interpreted as a function call. It's trying to call whatever was returned from the alert()
function, which of course returns undefined
, which isn't a function.
alert('foo') // alerts 'foo'
!function() {
alert('bar'); // alerts 'bar'
}()
No troubles with this one, since the !
is a unary operator that only evaluates the operand to its right.
Why write .call(this) at the end of an javascript anonymous function?
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.
Why use (function(){}).call(this);?
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.
self executing function invoked explicitly with call method
The second form passes the value of this
into the IIFE so this
inside the IIFE will have the same value that it had outside the IIFE. There are many cases where this does not make a difference, but if the IIFE is inside a scope where this
is set to some meaningful value, then the second form will preserve that value of this
inside the IIFE.
If this
in the outer scope is the global object and you are not running strict mode, then the 2nd form doesn't really change anything as this
will still be the global object inside the IIFE.
But, if this
is any meaningful value in strict mode or any meaningful value other than the global object when not in strict mode, then the 2nd form will extend the value of this
into the enclosure.
In the example you point to, my guess is that the second form is just being used as a common design pattern, not because there really is a reason in that particular case to do it. In fact, if you look at the code example you pointed to, it doesn't even use the value of this
at the top level of the IIFE so it's definitely superfluous in that specific example.
Why is .call(this) used instead of parenthesis
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).
Manually invoking anonymous JS function
You're close, the attempt you've shown is just not invoking it;
function confetti() {
// pass
}
confetti.call(this);
However as you want to use it elsewhere, I won't assume this
will be the same, so instead I would write
var confetti = (function () {
// pass
}).bind(this);
confetti();
You can read the docs on call
here and bind
here
Why would any body use this pattern?
Probably the writer wants to change the context of the IIFE. Passing this
would be pointless, since it will refer to window
even without the call
.
Something like this would change the meaning of this
in the scope:
(function () { console.log('Hello World', this) }).call({foo:1});
However, I still don't see the point, since you might as well do it like this:
(function (fooObj) { console.log('Hello World', fooObj) })({foo:1});
Which I would say is more common to see.
Why use the javascript function wrapper (added in coffeescript) .call(this)
It's creating a function and then calling itself with the parent function/objects scope.
.call and .apply are different methods of invoking a function. You basically created a function that does nothing except set a=1 within its own scope.
In javascript you need to realize that every function is a object, and this
is what refers to the current object/function. Using .call(this)
overrides this
from within the function and replaces it with the one from the calling context.
Related Topics
Why Are Objects Not Iterable in JavaScript
Google Bar Chart Cannot Change Individual Bar Color
Convert an Image into Binary Data in JavaScript
Get Keys of JSON-Object in JavaScript
Array Like Objects in JavaScript
How to Access Parent Window Object Using Jquery
Event Listener for When Element Becomes Visible
Getting Image Dimensions Using JavaScript File API
Typescript Compile to Single File
What the Difference Between .Click and .Change on a Checkbox
How to Serialize an Input File Object to JSON
Replace All Occurrences in a String
Is 'Window' Really Global in JavaScript
Dynamic Variables Names in JavaScript
How to Get the Index of an Array in a Meteor Template Each Loop
Convert a Directory Structure in the Filesystem to JSON with Node.Js