Why Do You Need to Invoke an Anonymous Function on the Same Line

Why do you need to invoke an anonymous function on the same line?

Drop the semicolon after the function definition.

(function (msg){alert(msg)})
('SO');

Above should work.

DEMO Page: https://jsfiddle.net/e7ooeq6m/

I have discussed this kind of pattern in this post:

jQuery and $ questions

EDIT:

If you look at ECMA script specification, there are 3 ways you can define a function. (Page 98, Section 13 Function Definition)

1. Using Function constructor

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2. Using Function declaration.

function sum(a, b)
{
return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3. Function Expression

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

So you may ask, what's the difference between declaration and expression?

From ECMA Script specification:

FunctionDeclaration :
function Identifier ( FormalParameterListopt ){ FunctionBody
}

FunctionExpression :
function Identifieropt ( FormalParameterListopt ){ FunctionBody
}

If you notice, 'identifier' is optional for function expression. And when you don't give an identifier, you create an anonymous function. It doesn't mean that you can't specify an identifier.

This means following is valid.

var sum = function mySum(a, b) { return a + b; }

Important point to note is that you can use 'mySum' only inside the mySum function body, not outside. See following example:

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise!

test1(); //alerts 'function' because test2 is a function.

Live Demo

Compare this to

 function test1() { alert(typeof test1) };

alert(typeof test1); //alerts 'function'

test1(); //alerts 'function'

Armed with this knowledge, let's try to analyze your code.

When you have code like,

    function(msg) { alert(msg); }

You created a function expression. And you can execute this function expression by wrapping it inside parenthesis.

    (function(msg) { alert(msg); })('SO'); //alerts SO.

Why is it useful to have an anonymous function stored as a variable, and pass it to higher order functions?

The brackets are only there when you're calling the function. If you pass the call with the brackets into the .filter() method, you'll actually be passing the result of the call, rather than a pointer to the call itself. The alternative is to pass in the entire function into the filter function, but readability tends to suffer. It also limits your ability to modify what's going into the function you're putting it in.

Imagine a case where you might want to do a sort instead of a filter, and you wanted to change the sort based on a boolean passed in.

Take this basic sort for example:

var numbers = [4, 2, 5, 1, 3];

numbers.sort(function(a, b) {
return a - b;
});

What if you wanted to be able to choose which direction it was sorted based on another variable. You can define both sort functions, and then pass the correct one for the sort you want.

var numbers = [4, 2, 5, 1, 3];
var sortAscending = function(a, b) {
return a - b;
}

var sortDescending = function(a, b) {
return b - a;
}

function doSort(myArray, dir) {
var sortMethod = (dir == "asc") ? sortAscending : sortDescending;
myArray.sort(sortMethod );
}

doSort(numbers, "asc");

The above illustrates how passing the method call this way allows for more flexibility when you need it, and ensures the call is made only when it's executed inside sort.

Why do I have to use an anonymous function instead of passing an additional argument to `setTimeout`?

The difference is the moment in time at which rAF is evaluated.

Explanation

Presumably, your code looks something like this:

let rAF;
const draw = () => {
// Do some work.

rAF = requestAnimationFrame(draw);
};

rAF = requestAnimationFrame(draw);

When you do this:

setTimeout(cancelAnimationFrame, 1000, rAF);

you pass three values to setTimeout: a function, a number, and another number.
When this statement is executed the call is evaluated, meaning that first, the setTimeout identifier is resolved to a function reference.
Second, the three arguments are evaluated: the cancelAnimationFrame identifier is resolved to a function reference, then the number literal is a number primitive, then the rAF identifier is resolved to another number primitive.
Then, the call is performed.

That’s all that setTimeout sees.
In JavaScript, you cannot pass a reference to a number, like you can in C, for example.

Let’s assume rAF is initially 1.
Over the course of one second, rAF has been repeatedly incremented and eventually reaches the value 61 or so.

Since you register the setTimeout at the start, the statement

setTimeout(cancelAnimationFrame, 1000, rAF);

is equivalent to

setTimeout(cancelAnimationFrame, 1000, 1);

However, the statement

setTimeout(() => cancelAnimationFrame(rAF), 1000);

is not equivalent to

setTimeout(() => cancelAnimationFrame(1), 1000);

The function bodies are only evaluated when they are called.
This means, JS doesn’t “peek inside the functions” and attempt to evaluate variables.
That statement essentially means “call some function with some other function and the number 1000 as arguments”.

When the one second is over and it’s time to cancel the animation frame, setTimeout executes its callback.
If the callback is () => cancelAnimationFrame(rAF), then it’s executed, so the function body is evaluated: cancelAnimationFrame(rAF) is equivalent to cancelAnimationFrame(61).

However, in the non-working case, cancelAnimationFrame stays the same, the argument 1 (equivalent to rAF at the time setTimeout was originally called) stays the same.
You can’t cancel frame 1 when you’re already at frame 61.

And setTimeout(alert, 1000, "Hello"); works, of course, because "Hello" is static, is only evaluated once, never changes.

Related

Here’s a more general situation where this behavior can be examined:

let greeting = "Hello";
const greet = (theGreeting) => console.log(`${theGreeting}, world!`);
const boundGreeting = greet.bind(null, greeting);

greeting = "Goodbye";

boundGreeting(); // Logs "Hello, world!".
greet(greeting); // Logs "Goodbye, world!".

Why does wrapping a callback in an anonymous function change the meaning of 'this'?

Using an anonymous function wraps MyObj in a closure. That closure's lexical scope (execution context) is now localized to the closure. So this is localized to the closure (and MyObj) as well.

You can discover that by using a debugger with a break point set on the callback() call.

This image shows the variable structure with the closure in place:

With anonymous function wrapper

Without the function wrapper, the lexical scope is the same scope as the higherOrder() function - which is the global scope. Again, this is demonstrated with a break point on the same line of code (note lack of closure):

Without wrapper

Note: this code is run in node - so no Window object here.

Rider - keep anonymous function block argument on same line as function call

These settings should work (File | Settings | Editor | Code Style | C#):

  1. On "Braces Layout" tab change "Anonymous method declaration" to "At
    end of line"
  2. On "Line Breaks and Wrapping" tab uncheck "Prefer wrap
    before "(" in invocation" and "Prefer wrap before ")" in invocation"

JavaScript anonymous function immediate invocation/execution (expression vs. declaration)

The first two cases show function expressions, and can appear anywhere an expression like (1+1 or x*f(4)) would appear. Just like how 1+1, evaluates to 2, these expressions evaluate to a corresponding function.


The third case is a function declation statement, and can appear anywhere you can have other statements (like an if or while statement).

There is not much point in trying to declare an anonymous function via a Funcion declaration statements, since otherwise noone would get a reference to the function afterwards.


The reason you need the opening ( or the var x = like in the first two cases is that they force next bit to be parsed in an expression context. (just think how you cant do var x = if ..., for example). If you just put the function as the first thing it will be parsed as the declaration statement you don't want.

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).

Why can't I use an anonymous function expression for accessing an array index position?

() => 0 returns a function, not the value returned when called.

You need to invoke the function instead:

const arr = ["one", "two", "three"];
console.log(arr[(() => 0)()]);


Related Topics



Leave a reply



Submit