What's the meaning of "Function definitions may not appear within statements" - javascript

What's the meaning of this "Function definitions may not appear within if statements, while loops, or any other statements." I'm quite confuse with this statement.

One issue with what you're reading in the book is that a function definition (which is different than a function assignment) is essentially hoisted to the top of the host function in some browsers so putting it inside a statement (like inside an if statement) is downright misleading. The code will make it look like the function will only be defined if that branch of the if statement executes, but that will not necessarily be the case. So, it's a bad practice. It probably works in many cases, but is a bad practice.
So, rather than this:
function main(foo) {
if (foo) {
function internal() {
// code here
}
// code here
}
}
Put the internal function up at the top;
function main(foo) {
function internal() {
// code here
}
if (foo) {
// code here
}
}
FYI, in strict mode internal function definitions are only allowed at the top. Condition function assignments can always be done with this syntax:
var internal;
if (foo) {
internal = function() {}
}

Related

Function declarations cannot be nested within non-function blocks

I am reading about Function Declarations vs. Function Expressions, and I cannot figure out the meaning of following statement:
Function Declarations occur as standalone constructs and cannot be
nested within non-function blocks.
Someone please to explain with an exemple what does the author means, precisely by: "...cannot be nested within non-function blocks".
Link is: https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
I dont know the author meant it was physically impossible or more of it shouldn't be done. From my understanding what the author was saying is that this:
var y = true;
if (y) {
function example() {
alert('hi');
return true;
}
}
Here the function is declared inside a conditional statement, which is fine since x is true, but if it were false that function would never be declared and when we do want to the call the example function nothing will happen because it was never declared. So it should be
function example() {
"use strict";
return true;
}
var y = true;
if (y) {
example();
}
In the above code we still call the example function if the condition is met, however since example is defined outside the condition statement we can use it regardless of the conditional statement. This Post has more information about it. Hopefully this is what you meant
Taken at face value, the statement:
Function Declarations occur as standalone constructs and cannot be nested within non-function blocks.
is wrong. It's possible to put function declarations inside blocks, as examples in the article show. The reason that it's warned against is that the behaviour differs in different browsers. In most browsers (not certain versions of IE and Firefox), such functions are declared regardless of whether execution enters the block or not, e.g.:
if (false) {
function foo(){}
}
foo is declared and available within the outer scope. This is exactly the same with variable declarations:
if (false) {
var x = 3;
}
In the above, x is declared regardless of whether the block is executed or not. The assignment of the value, however, only occurs if the block is entered.
Back to functions. The reason function declarations in blocks is warned against is that firstly, it infers that the function is only created if the block is entered, which is incorrect for most browsers but not all. Secondly, and more importantly, it's because different browsers have different behaviour.
Some interesting reading:
Richard Cornford: FunctionExpressions and memory consumption
Kangax: Function statements
What are the precise semantics of block-level functions in ES6?
Also note that function statements are warned against in ES5 strict mode and may be introduced in some future version of ECMAScript.
Finally, this behaviour is addressed directly in ECMA-262 ed 6 in Appendix B 3.3.3 and Appendix B 3.4.
I think it means you cannot define functions arbitrarily in the code, see below.
if true {
function funName(){};
}
funName will not be a function in this case, it will cause an error.
Consider the humble if statement:
function whatever() {
// ...
if (something === somethingElse) {
function aFunction() {
// ...
}
// more code ...
}
aFunction(5, 6, 7);
Now, that code is weird. The function is declared inside the if block. But function declarations are hoisted! So what does that mean?
More weird: what if there's a different declaration for "aFunction" in the else clause?
A fundamental aspect of the weirdness from code like that is that function declarations are treated as if they occur at the top of the scope (that is, they're "hoisted"). For that reason, a function declaration inside some other sort of block is just inherently ambiguous and strange.
Note that function instantiation via function expressions are not weird, because those happen as part of running code, like object initialization expressions.

What's the difference between naming a function (as opposed to leaving it anon) and creating a reference to it?

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.

What does it mean when a variable equals a function? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
In JavaScript, what's the purpose of defining a variable as a function? I've seen this convention before and don't fully understand it.
For example, at some point in a script, a function is called like this:
whatever();
But where I would expect to see a function named whatever, like this:
function whatever(){
}
Instead I'll see a variable called whatever that's defined as a function, like this:
var whatever = function(){
}
What's the purpose of this? Why would you do this instead of just naming the function?
Note: Please see the update at the end of the answer, declarations within blocks became valid (but quite complicated if you're not using strict mode).
Here's one reason:
var whatever;
if (some_condition) {
whatever = function() {
// Do something
};
}
else {
whatever = function() {
// Do something else
};
}
whatever();
You might see code like that in the initialization of a library that has to handle implementation differences (such as differences between web browsers, a'la IE's attachEvent vs. the standard addEventListener). You cannot do the equivalent with a function declaration:
if (some_condition) {
function whatever() { // <=== DON'T DO THIS
// Do something
}
}
else {
function whatever() { // <=== IT'S INVALID
// Do something else
}
}
whatever();
...they're not specified within control structures, so JavaScript engines are allowed to do what they want, and different engines have done different things. (Edit: Again, see note below, they're specified now.)
Separately, there's a big difference between
var whatever = function() {
// ...
};
and
function whatever() {
// ...
}
The first is a function expression, and it's evaluated when the code reaches that point in the step-by-step execution of the context (e.g., the function it's in, or the step-by-step execution of global code). It also results in an anonymous function (the variable referring to it has a name, but the function does not, which has implications for helping your tools to help you).
The second is a function declaration, and it's evaluated upon entry to the context, before any step-by-step code is executed. (Some call this "hoisting" because something further down in the source happens earlier than something higher up in the source.) The function is also given a proper name.
So consider:
function foo() {
doSomething();
doSomethingElse();
console.log("typeof bar = " + typeof bar); // Logs "function"
function bar() {
}
}
whereas
function foo() {
doSomething();
doSomethingElse();
console.log("typeof bar = " + typeof bar); // Logs "undefined"
var bar = function() {
};
}
In the first example, with the declaration, the declaration is processed before the doSomething and other stepwise code is run. In the second example, because it's an expression, it's executed as part of the stepwise code and so the function isn't defined up above (the variable is defined up above, because var is also "hoisted").
And winding up: For the moment, you can't do this in general client-side web stuff:
var bar = function foo() { // <=== Don't do this in client-side code for now
// ...
};
You should be able to do that, it's called a named function expression and it's a function expression that gives the function a proper name. But various JavaScript engines at various times have gotten it wrong, and IE continued to get very wrong indeed until very recently.
Update for ES2015+
As of ES2015 (aka "ES6"), function declarations within blocks were added to the specification.
Strict mode
In strict mode, the newly-specified behavior is simple and easy to understand: They're scoped to the block in which they occur, and are hoisted to the top of it.
So this:
"use strict";
if (Math.random() < 0.5) {
foo();
function foo() {
console.log("low");
}
} else {
foo();
function foo() {
console.log("high");
}
}
console.log(typeof foo); // undefined
(Note how the calls to the functions are above the functions within the blocks.)
...is essentially equivalent to this:
"use strict";
if (Math.random() < 0.5) {
let foo = function() {
console.log("low");
};
foo();
} else {
let foo = function() {
console.log("high");
};
foo();
}
console.log(typeof foo); // undefined
Loose mode
Loose mode behavior is much more complex and moreover in theory it varies between JavaScript engines in web browsers and JavaScript engines not in web browsers. I won't get into it here. Just don't do it. If you insist on function declarations within blocks, use strict mode, where they make sense and are consistent across environments.
this is so you can store functions in variables and e.g. pass them to other functions as parameters. One example where this is usefull is in writing asynchronous functions which are passed callbacks as arguments
var callback = function() { console.log('done', result)}
var dosomething = function(callback) {
//do some stuff here
...
result = 1;
callback(result);
}
Since functions are objects in javascript you can extend them with properties and methods as well.
Functions in JavaScript are objects; they're values, in other words. Thus you can always set a variable to refer to a function regardless of how the function is defined:
function foo() { ... }
var anotherFoo = foo;
anotherFoo(); // calls foo
Functions are values that can be used as object properties, function parameters, array elements, and anything else a general value can do in JavaScript. They're objects and can have their own properties too.
When you assign a function to a variable, you can then pass it around as an argument to other functions, and also extend it to make use of Javascript's Object model.
If you declare a functionvariable, using "var", within a function, the variable can only be accessed within that function. When you exit the function, the variable is destroyed. These variables are called local variables. You can have local variables with the same name in different functions, because each is recognized only by the function in which it is declared.

Why does second function declaration win even though I return before it?

I have the following JavaScript code:
(function() {
function f(){ alert(1); }
return f();
function f(){ alert(2); }
})();
Can you explain why the alert pops up with 2 and not 1?
Thanks,
This gets into what happens when execution enters a function: Leaving out a lot of detail, all function declarations (the style you've used) are processed, and only after that does step-by-step code execution occur. So your return statement has no impact on which function declaration is chosen. And the declaration chosen is always the last one in source code order (this is covered — in wonderfully turgid prose — in Section 10.5 of the specification).
The result would be fundamentally different if you used function expressions, which are evaluated as part of step-by-step code:
(function() {
var f;
f = function(){ alert(1); };
return f();
f = function(){ alert(2); };
})();
This code is technically incorrect (because you have code following a return that will always be followed), but it illustrates the difference: You see the alert(1) happen rather than the alert(2), because those expressions are not evaluated until they're reached.
You can read more about what happens when execution enters a function (declarations aren't the only thing that are done prior to the first step-by-step code) in Sections 10.4.3 and 10.5 of the specification.
And with your new knowledge, a quiz: What happens here? (Note: Never do this.)
function foo() {
if (true) {
function bar() {
alert(1);
}
}
else {
function bar() {
alert(2);
}
}
bar();
}
foo();
The answer is: It varies, don't do that. Some engines will use the first bar, other engines will use the second, and others will call it a syntax error. This is because this actually is an error, and so engines are free to do what they think best. If you look closely at the language grammar, you'll see that it's invalid to put function declarations inside branches within their immediately-containing scope. They must be at the top level of that scope. With your new understanding of declarations, the reason should be obvious: They're not related to the flow of execution within the scope, and so naturally you can't choose them based on that flow of execution.
So what happens in the real world? Sadly, usually not an error if you're in "loose" mode (not strict). Some engines (Chrome's V8 for example, as of this writing) will ignore the flow control statements and just pick the last function declared (and so you get the counter-intuitive result that the second bar function is used), other engines (Firefox's SpiderMonkey, IE11's JScript) effectively rewrite your code on the fly turning those declarations into expressions instead, and so you get the first bar. E.g., it will vary by engine. The good news is that if you try this in strict mode, all three of those (V8, SpiderMonkey, and IE11's JScript) will fail rather than picking one (V8 and SpiderMonkey with nice clear error messages in the console; JScript with just the surprising "bar is undefined", but...).
If you want to do something like the above, but valid and consistent across engines, use expressions:
function foo() {
var bar;
if (true) {
bar = function() {
alert(1);
};
}
else {
bar = function() {
alert(2);
};
}
bar();
}
foo();
There's a fun exploration of this on kangax's Named Function Expressions Demystified page.
There is something that is called "hoisting" - it's a corollary of scope/function activation resolution process (without going into too much details).
What that means is that at entering the scope of the function of variable and function declarations are processed and stored as if they were made at the beginning of the scope. The assignment parts are left where they are.
So the following code:
function()
{
console.log(a)
var a = 5;
}
will print "undefined", and that is because, simply put, it is equivalent to:
function()
{
var a;
console.log(a)
a = 5;
}
In you example - there is an important thing to remember - these are function declarations - so they are processed as any variable would be, but since they "contain" the function body, then the whole declaration (including equivalent of a = 5) is "hoisted".
During that variables processing stage - if there already has been processed a variable of the same name - it's value and attributes are replaced.
So you code is equivalent to:
(function() {
function f(){ alert(2); }
return f();
})();
Because the body of the anonymous function isn't procedural as you might expect.
Rather it's an object with properties. And you're allowed forward references - that is, code in one function can refer to properties that are defined later on in the object.
Since you have duplicate definitions of the same property, the latter one takes precedence, effectively overwriting the first. So your snippet is equivalent to (removing the first, overridden definition):
(function() {
return f();
function f(){ alert(2); }
})();
and at this point it should come as no surprise to you that the alert contains 2.
Because code is first parsed, the f() function is underwritten, than it is executed, and the last f() function is called.

JSlint error 'Don't make functions within a loop.' leads to question about Javascript itself

I have some code that invokes anonymous functions within a loop, something like this pseudo example:
for (i = 0; i < numCards; i = i + 1) {
card = $('<div>').bind('isPopulated', function (ev) {
var card = $(ev.currentTarget);
....
JSLint reports the error 'Don't make functions within a loop.' I like to keep my code JSLint clean. I know I can move the anonymous function out of the loop and invoke it as a named function. That aside, here's my question:
Would a Javascript interpreter really create an instance of the function per iteration? Or is there really only one function instance "compiled" and the same code is executed repeatedly? That is, does the JSLint "suggestion" to move the function out of the loop actually affect the efficiency of the code?
Partially it depends on whether you're using a function expression or a function declaration. They're different things, they happen at different times, and they have a different effect on the surrounding scope. So let's start with the distinction.
A function expression is a function production where you're using the result as a right-hand value — e.g., you're assigning the result to a variable or property, or passing it into a function as a parameter, etc. These are all function expressions:
setTimeout(function() { ... }, 1000);
var f = function() { ... };
var named = function bar() { ... };
(Don't use that last one — which is called a named function expression — implementations have bugs, particularly IE.)
In contrast, this is a function declaration:
function bar() { ... }
It's stand-alone, you're not using the result as a right-hand value.
The two main differences between them:
Function expressions are evaluated where they're encountered in the program flow. Declarations are evaluated when control enters the containing scope (e.g., the containing function, or the global scope).
The name of the function (if it has one) is defined in the containing scope for a function declaration. It is not for a function expression (barring browser bugs).
Your anonymous functions are function expressions, and so barring the interpreter doing optimization (which it's free to do), they'll get recreated on each loop. So your use is fine if you think implementations will optimize, but breaking it out into a named function has other benefits and — importantly — doesn't cost you anything. Also, see casablanca's answer for a note about why the interpreter may not be able to optimize out recreating the function on each iteration, depending on how deeply it inspects your code.
The bigger issue would be if you used a function declaration in a loop, the body of a conditional, etc.:
function foo() {
for (i = 0; i < limit; ++i) {
function bar() { ... } // <== Don't do this
bar();
}
}
Technically, a close read of the spec's grammar shows it's invalid to do that, although virtually no implementation actually enforces that. What the implemenations do is varied and it's best to stay away from it.
For my money, your best bet is to use a single function declaration, like this:
function foo() {
for (i = 0; i < limit; ++i) {
bar();
}
function bar() {
/* ...do something, possibly using 'i'... */
}
}
You get the same result, there's no possibility that an implementation will create a new function on every loop, you get the benefit of the function having a name, and you don't lose anything.
Would a Javascript interpreter really create an instance of the function per iteration?
It has to because it doesn't know if the function object will be modified elsewhere. Remember that functions are standard JavaScript objects, so they can have properties like any other object. When you do this:
card = $('<div>').bind('isPopulated', function (ev) { ... })
for all you know, bind could modify the object, for example:
function bind(str, fn) {
fn.foo = str;
}
Clearly this would result in wrong behaviour if the function object was shared across all iterations.
The interpreter may actually create a new function object with every iteration, if only because that function might be a closure that needs to capture the current value of any variable in its outer scope.
That's why JSLint wants to scare you away from creating many anonymous functions in a tight loop.
Boo to JSLint. It's like a blunt instrument on the head. A new function object is created each time function is encountered (it is a statement/expression, not declaration -- edit: this is a white lie. See T.J. Crowders answers). Usually this is done in a loop for a closure, etc. The bigger issue is creating false closures.
For instance:
for (var i = 0; i < 10; i++) {
setTimeout(function () {
alert(i)
}, 10)
}
Will result in "odd" behavior. This isn't an issue with "creating a function in a loop so much as not understanding the rules JS uses for variable scopes and closures (variables are not bound in closures, scopes -- execution contexts -- are).
However, you may want to create a closure in a function. Consider this less-surprising code:
for (var i = 0; i < 10; i++) {
setTimeout((function (_i) {
return function () {
alert(_i)
}
})(i), 10)
}
Oh no! I still created a function!

Categories