Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a function passed to a JQuery handler

function test() {
  var str = 'adarsh';

  // f1(); - This gives an error.
  $('body').click(function f1() {
    console.log(str);
  });
}

test();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

I want to know why the above snippet gives an error when I try to access f1() inside the function test.

What is the function f1 scoped to?
I know it is not the window because I cannot access window.f1 after executing the above snippet.

Note: I know I can declare function f1 first and then pass the reference to it in the click function. However I want to know what is the point of naming 'anonymous' functions in such contexts if we cannot access them anywhere through that name.

like image 739
Adarsh Konchady Avatar asked Jul 22 '26 02:07

Adarsh Konchady


2 Answers

A function declaration will:

  • Create a variable with the same name as the function in the current scope.

A named function expression (which is what you have here) will:

  • Create a variable with the same name as the function inside the scope of that function (which is useful for calling itself recursively).
  • Evaluate as the function

So there are two ways you can access the function you created with the named function expression:

  • Put something on the left hand side of the expression. In this case you are already doing that by passing it to click(), so the click function can do something with it
  • Call it by name from inside itself

There are no further references to it in the scope of test.

However I want to know what is the point of naming 'anonymous' functions in such contexts if we cannot access them anywhere through that name.

As I said, the variable is useful for calling it recursively.

The name (which is different to the variable) is also useful as it shows up in debuggers. It is a lot easier to deal with a stacktrace consisting of a dozen useful names than one which is just a dozen repetitions of (anonymous function).

like image 113
Quentin Avatar answered Jul 23 '26 15:07

Quentin


The BindingIdentifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the BindingIdentifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression. @@ http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-runtime-semantics-evaluation

In other words, when you have a function expression like function someName() {...} (not to confuse with a function declaration) the name is bound inside the function, not in the containing scope.

fun = function someName() {
  
  alert(someName);  // works
  
};  

alert(typeof someName); // doesn't work

fun();

The purpose of giving names to function expressions is to have meaningful stack traces.

like image 36
georg Avatar answered Jul 23 '26 16:07

georg