The following is probably a bit senseless, but why does the first call below work while the second one fails?
var foo = function bar() {
console.log("Martini");
}
foo(); // works
bar(); // undefined; i.e. "Uncaught ReferenceError: bar is not defined"
Has that to do with scope?
Corollary beginner's question: The function definition "parses" - but is that actually valid syntax - and is there any context where naming an assigned anonymous function makes sense?
Function declarations create a variable with the same name as them in the current scope.
Function expressions (named or anonymous) do not. The name of a function expression is available as a variable inside the function (where it is useful for calling itself recursively) and in debugging tools.
Related
I am learning the hoisting concept in javascript. One piece of code which blocked me is this:
function foo() {
console.log(8);
}
var foo;
console.log(foo);
Question 1:
I typed in this code in chrome console, print out is
function foo(){
console.log(8)
}
would the variable declaration overwrite the function declaration? I think the print out should be undefined
Question 2:
I typed in the same code in an online editer https://jsbin.com/dezixozewi/edit?js,console, it throws error as 'Identifier 'foo' has already been declared'. so it does not allow duplicate declaration at all.
Could any one help to explain the logic behind? Thanks a lot in advance!
The reason the function is the value of foo is because in this line:
var foo;
You're just stating foo - that's a statement that doesn't do anything.
If you actually set foo to something, for example "FooBar":
function foo() {
console.log(8);
}
var foo = "FooBar";
console.log(foo);
It overwrites the function, because as shown in this question, declaring anything with var that is a value will result in that value being "hoisted" to the top, and as such being the actual value of the identifier.
would the variable declaration overwrite the function declaration?
No. Before any code is executed, the runtime finds all function and variable declarations and initializes the new scope with them. Things vary slightly between evaluating script code and evaluating function scope, but the result is the same:
Duplicate declarations are ignored.
Function declaration are evaluated at the end and assigned to their respective name.
In global scope, because foo is both a function name as well as a variable declaration, the variable declaration is ignored. And since it doesn't have an initializer, the value of foo doesn't change when that line is actually evaluated.
The details can be found in the language specification.
Question 2: I typed in the same code in an online editer https://jsbin.com/dezixozewi/edit?js,console, it throws error as 'Identifier 'foo' has already been declared'. so it does not allow duplicate declaration at all.
Unclear how jsbin evaluates the code, but it is valid.
var foo; statement declares foo variable and set it's value to undefined if it already has not a value. Your foo has a value, since the var foo; actually doesn't do anything.
If you remove the foo function and replace it with a simple variable, you will see the same behaviour.
var foo; simply points to the memory location of foo. It happens that you've already declared a function there, so that's why the value of foo is just still the function.
It's no different than if you did:
var x = 2;
var x; // We're not setting a value with `=`, so nothing gets overridden
x; // 2
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().
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the (function() { } )() construct in JavaScript?
I came across this bit of JavaScript code, but I have no idea what to make out of it. Why do I get "1" when I run this code? What is this strange little appendix of (1) and why is the function wrapped in parentheses?
(function(x){
delete x;
return x;
})(1);
There are a few things going on here. First is the immediately invoked function expression (IIFE) pattern:
(function() {
// Some code
})();
This provides a way to execute some JavaScript code in its own scope. It's usually used so that any variables created within the function won't affect the global scope. You could use this instead:
function foo() {
// Some code
}
foo();
But this requires giving a name to the function, which is not always necessary. Using a named function also means at some future point the function could be called again which might not be desirable. By using an anonymous function in this manner you ensure it's only executed once.
This syntax is invalid:
function() {
// Some code
}();
Because you have to wrap the function in parentheses in order to make it parse as an expression. More information is here: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
So to recap quickly on the IIFE pattern:
(function() {
// Some code
})();
Allows 'some code' to be executed immediately, as if it was just written inline, but also within its own scope so as not to affect the global namespace (and thus potentially interfere with or be interfered with by, other scripts).
You can pass arguments to your function just as you would a normal function, for example,
(function(x) {
// Some code
})(1);
So we're passing the value '1' as the first argument to the function, which receives it as a locally scoped variable, named x.
Secondly, you have the guts of the function code itself:
delete x;
return x;
The delete operator will remove properties from objects. It doesn't delete variables. So;
var foo = {'bar':4, 'baz':5};
delete foo.bar;
console.log(foo);
Results in this being logged:
{'baz':5}
Whereas,
var foo = 4;
delete foo;
console.log(foo);
will log the value 4, because foo is a variable not a property and so it can't be deleted.
Many people assume that delete can delete variables, because of the way autoglobals work. If you assign to a variable without declaring it first, it will not actually become a variable, but a property on the global object:
bar = 4; // Note the lack of 'var'. Bad practice! Don't ever do this!
delete bar;
console.log(bar); // Error - bar is not defined.
This time the delete works, because you're not deleting a variable, but a property on the global object. In effect, the previous snippet is equivalent to this:
window.bar = 4;
delete window.bar;
console.log(window.bar);
And now you can see how it's analogous to the foo object example and not the foo variable example.
It means you created an anonymous function, and call it with parameter 1.
It is just the same as:
function foo(x) {
delete x;
return x;
}
foo(1);
The reason that you still get 1 returned is that the delete keyword is for removing properties of objects. The rest is as others have commented, anything wrapped in brackets executes as a function, and the second set of brackets are the arguments passed to that block.
Here's the MDN reference for delete, and the MDN reference for closures, which discusses also anonymous functions.
People normally call these "Immediately Invoked Function Expressions" or "Self Executing Functions".
The point of doing this is that variables declared inside that function do not leak to the outside.