Please see this code example:
var myFunc = function () {
alert("hello world");
})();
This is a function expression, which is not hoisted. So my presumption here is that it runs only when the code gets to its actual position within the code. Is this true?
This is a function expression, which is not hoisted.
Yes. Function expressions are not hoisted (self-invoking or otherwise).
What's more, there are no references to the function stored anywhere, so there isn't anything to hoist in the first place.
So my presumption here is that it runs only…
Function declarations are hoisted, but that has nothing to do with when they are run. Just when the variable name matching the function name gets it's value (so it can be used to call the function).
A function only runs when it is called.
In your code, then is when the () after the function body are processed.
The var declaration of myFunc, like all var declarations, will be hosted. It will get an initial value of undefined and then, when the function runs, it will get the return value (also undefined) of that function.
Yes you are correct.
Function expressions in JavaScript are not hoisted, unlike function declarations. You can't use function expressions before you define them
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function
Related
According to hoisting definition:
Hoisting is a JavaScript mechanism where variables and function
declarations are moved to the top of their scope before code execution
Why do function declarations get hoisted and function expressions don't?
As per MDN,
Conceptually, for example, a strict definition of hoisting suggests that variable and function declarations are physically moved to the top of your code, but this is not in fact what happens. Instead, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code.
As you see, in a function expression, actual function is a value assigned to a named variable. So this named variable is hoisted. Even if you have a named function assigned, it still will not be hoisted as it is not a declaration and will be created later.
Sample:
function test() {
console.log(fn, foo);
var fn = function foo() {}
}
test();
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.
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).
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.
What is the function 'f1' scoped to?
It's not scoped to anything. The reference of the function is provided to the handler only, so there is nothing else defined which points to that function. If you want to define the function so that it can be called in multiple places you would need to change your logic to something like this:
function test() {
var str = 'adarsh';
$('body').click(function() { // < note the anonymous function here
f1(str);
});
}
function f1(str) {
console.log(str);
}
test();
f1('foo bar');
Calling a function passed to a JQuery handler
You can use jQuery._data() to access and call the event handler of click, f1, outside of .click()
function test() {
var str = "adarsh";
// f1(); - This gives an error.
$("body").click(function f1() {
console.log(str);
});
var ref = $._data(document.body, "events")["click"][0];
console.log(ref.handler, ref.handler.name);
ref.handler()
}
test();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>click</body>
Code:
var funcExpression = function(){
alert("function expression");
}();
(function declarFunc(){
alert("declared func");
})();
The result is the function Expression is run first resulting in the alert "function expression" and the declared function is run second "declared func".
I know that during the hoisting process, declared functions are hoisted up entirely within their container and loaded into memory. Function expressions, however are not hoisted: they stay in the same place and are not loaded into memory until runtime(though the variable that points to the function expression is hoisted up and set to Undefined. (Please correct me if I have this concept wrong)
Since, the declared function is hoisted up above the function expression assignment, I would expect thus that the declared function is executed first: resulting in the alert "declared func" and then the function expression is executed afterwards: resulting in the second alert of "function expression".
However: it doesn't do what I expect. Thus, it seems like it has something to do with the immediate invocations of both the functions. Maybe the immediate invocations stay in the same order? Maybe after the hoisting process the code really looks like this:
var funcExpression = Undefined;
(function declarFunc(){
alert("declared func");
})
funcExpression = function(){
alert("function expression");
}();
(); // this executes declarFunc. Maybe declarFunc is hoisted up
// but the invoking part stays in the same place?
Solution after feedback and additional research
The answer is that BOTH of those functions are function expressions:
Code:
var funcExpression = function(){
alert("function expression");
}();
(function declarFunc(){
alert("declared func");
})();
so declareFunc() looks like a declared function, but since it is wrapped in parenthesis like that, it transforms it into a named function expression. The parenthesis following immediately evokes this function expression.
I was having trouble showing what the code looks like after the hoisting process because (function declarFunc(){...})() transforms into a named function expression due to those wrapping parenthesis. What this means is that outside of this named functions scope, we have no way to call it.
Example: If after these functions I did declarFunc() it will return with the error: ReferenceError: Can't find variable: declarFunc.
If we did want to make it possible to run this function expression then we would want to assign the function expression to a variable:
var foo = function declarFunc(){
alert("declared func");
};
Note: If we look at the console we will see that console.log(foo()) will return undefined, but the actions of the function will still take place. Just know that if no return statement is specified, then it implicitly returns undefined.
And now we can call on that function as many times as we would like with foo().
I read in a book about function declaration. The code goes like this.
function outer(){
assert(typeof inner === "function", "inner() in scope before declaration");
function inner(){}
assert(typeof inner === "function", "inner() in scope after declaration");
assert(typeof window.inner === "undefined", "inner() undefined in global space")
}
When the tests are run all the three statements are asserted true, showing that the inner() function existed in scope before its declaration. My concept about javascript is that the script is executed line by line and the functions should be declared before there call.
The question is how can the inner function exist in the scope before its declaration?
My concept about javascript is that the script is executed line by line and the functions should be declared before there call.
That's incorrect. In JavaScript, all function declarations in an execution context are processed upon entry into that execution context, before any step-by-step code is executed. So function declarations within functions are processed upon entry into the function when it gets called, and function declarations at global scope are processed before any global step-by-step code is executed. This is sometimes called "hoisting" (because the function declarations are effectively "hoisted" [lifted] up to the top of the scope they're declared in). (Side note: var is also hoisted, more on my blog: Poor misunderstood var.)
This is distinct from function expressions, which like all expressions, are evaluated in the step-by-step execution of the code.
Here's a function declaration:
function foo() { }
Here are three function expressions, note that in each case, they're used as right-hand values (e.g., they're assigned to a var or property, passed into a function, used in a containing expression, etc.), which is what makes them expressions rather than declarations:
var x = function foo() { };
obj = {
b: function bar() { }
};
doSomethingWith(function() { });
There I've shown two named function expressions and one anonymous function expression. If you're going to be writing code for IE8 and earlier, you may want to steer clear of named function expressions as IE's "JScript" interpreter gets them wrong; more (also my blog): Double take.
Javascript executes a function in two Pass, consider this :
There are two ways that you can use a function
1st: function quack(num){
for(var i=0; i<num ; i++)
{
console.log("quacking")
}
} - this is a function declaration.
2nd: var fly = function(num){
for(var i=0; i<num ; i++)
{
console.log("Flying!!!")
}
} - This is a function expression.
Now in the first pass the javascript looks for function declaration
which is
function quack(num){
for(var i=0; i<num ; i++)
{
console.log("quacking")
}
}
So it assigns quack's reference to a variable
which has the same name as that of the method ie.. quack .
So if you call quack() before you declare it, it works fine.
However in the 2nd pass it looks for function expression which
means you cannot call fly before evaluating it.
I hope this gives a better explanation.
In a comment on another thread I started, someone said this:
#adlwalrus yes. try this: var foo = function bar(){}; console.log(foo); But be aware that bar is only function name (what does it mean I'm not sure exactly myself) and not a reference to it, so you can't call it by doing bar(). And assigning (even named function) is not the same as declaring a function. Hoisting (bumping to top of the scope) only works for declarations, assignment will stay in place. – valentinas 6 hours ago
What purpose does a function name serve if you can't call it with bar()?
For the function to call itself.
var x = function y(val){
if (val){
console.log(val);
y(val-1);
}
};
x(5);
> 3
> 2
> 1
y(3);
> ReferenceError: y is not defined
You're referring to a named function expression. The spec requires that the name of such functions only be available within the scope of the new function. Spec quote:
The Identifier 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
Identifier in a FunctionExpression cannot be referenced from and does
not affect the scope enclosing the FunctionExpression.
On the other hand, the result of that expression is a reference to the new function, which can be saved and referenced anywhere.
Lots of details here:
http://kangax.github.com/nfe/#named-expr
I'd read the whole thing.
As for benefits, another is that it makes them easier to identify in a debugger.
There are two ways to create a function in JavaScript, a "function declaration" and a "function expression." I believe it was Doug Crockford who explained it best when he pointed out that unless "function" is the very first set of characters on a given line, you're performing a function expression (not a declaration).
Function declarations are finicky creatures. You'll recognize them when you see them. They look like this:
function foo() { /* ... */ }
They're always given a name (it's requited) and the name is locally scoped to the lexical context under which the function is declared. So if you perform a function declaration in the global context, then the function can be referenced via it's name globally. If you do it within a function, the function's name can be referenced only within that function and any functions declared within that function.
I think the most important aspect of this method of declaring a function (one that is rarely commented on) is that the function initialization gets hoisted to the top of the current lexical context. Therefore, you should never, ever use a function declaration within a conditional, such as this:
//DON'T DO THIS!
if (x) {
function foo() { return 1; }
} else {
function foo() { return 2; }
}
foo(); //will always be 2, regardless of the value of x.
A function expression is slightly different. Often, they're directly assigned to a variable, like so:
var foo = function() { /* ... */ };
This is nearly identical to the function declaration above except that the initialization is not hoisted. So you can do the following:
var foo;
if (x) {
foo = function() { return 1; };
} else {
foo = function() { return 2; };
}
foo(); //will be 1 or 2, depending on the truthy-ness of x.
So, back to the original question. Function expressions can also have a name, though it's not required and it's not scoped to the context in which the function is declared (as with function declarations). Instead, it gets scoped to the function's own lexical context. This is very useful in some cases. My personal favorite is this pattern:
(function foo() {
//Do something.
setTimeout(foo, 1000);
}());
foo; //undefined
Because of the parenthesis before the word "function", this is a function expression and the name is scoped internally only. But that's okay, because we only need to call it internally (via setTimeout()). The result is that the function will execute once immediately, then will re-execute every second or so after it's finishes execution. This is safer than using setInterval() because it will wait until it's done executing before rescheduling itself, preventing overlaps that could cause missed executions and/or "domination" of the JavaScript thread.
Essentially, the use of a named function expression is limited, but when you need it, it's very powerful.