definition of functions javascript and firefox - javascript

I have this code:
function a() {
if(prodotto.approvatoIngredienti==true) {
disegnaIconaIngredienti();
function disegnaIconaIngredienti() {
//
}
}
I defined a function inside another function. With chrome and ie I don't have problem, but firefox gives me this error:
--
[15:26:41.279] disegnaIconaIngredienti is not defined # http://127.0.0.1:8080/Tesi/javascript/InserimentoProdotti.js:1718
Someone can explain me why?

You haven't closed your if statement on the second line.

Your code is equivalent in Firefox to
var disegnaIconaIngredienti;
if (prodotto.approvatoIngredienti==true){
disegnaIconaIngredienti();
disegnaIconaIngredienti = function(){
//
}
}
So the variable doesn't have a value when you call it.
Chrome and Internet Explorer hoist the whole function declaration and not only the variable declaration.
ECMAScript doesn't allow function definition in non function blocks (like your if). Browsers allow it but in different ways.
This related question goes deeper in the topic.

It's because firefox has something called function statements. They're different from typical declarations, and can legally happen in a block.
There's no hoisting of the function itself as you'd find with a declaration, so it needs to be defined before it's used.
Note that in typical ECMAScript, it's invalid to have that style of function inside an if statement, though some browsers allow it. Strict mode absolutely prohibits it.
To have a fully valid function created inside an if, it must be a function that is part of an expression, like an assignment.
function a(){
if(prodotto.approvatoIngredienti == true) {
// legal function in a block
var disegnaIconaIngredienti = function() {
//
};
disegnaIconaIngredienti();
}

You forgot to close the if brace
function a(){
if(prodotto.approvatoIngredienti==true){
disegnaIconaIngredienti();
}
function disegnaIconaIngredienti() {
//
}
}
After further consideration on your closing if and #dystroy's post
I tend to agree with him and say that Firefox doesn't permit using
part of his post to answer :
ECMAScript doesn't allow function definition in non function blocks (like your if). Browsers allow it but in different ways.
Like in your case where Firefox doesn't allow it inside conditional blocks.

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.

Function decaration in Javascript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between a function expression vs declaration in Javascript?
Is there a MAJOR difference between declaring functions in these ways:
function foo(){
alert('BAR');
}
var foo = function (){
alert('BAR');
}
var foo = function bar(){
alert('BAR');
}
I was told here that:
It happens at a different time, and results in a variable referring to an anonymous function. A function declaration happens prior to any stepwise code executing in the scope, and results in both a binding and a function with a proper name.
Can the way I declare my function really affect the efficiency of my code, and if so which way is best to use?
Yes, there is a major difference.
The first is a function declaration. It happens upon entry to an execution context, prior to any step-by-step code being processed. It cannot be within any kind of control block (e.g., it's not legal in the body of an if statement; however, most browsers will try to accommodate it if you do that — sometimes resulting in very surprising behavior — at variance with the spec). It results in a named function.
The second is a function expression (specifically, an anonymous function expression). Like all expressions, it's processed when it's encountered in the step-by-step execution of the code. And like all expressions, it can be within a control block. It results in a function with no name assigned to a variable that has a name.
The third is a named function expression. It's a function expression like the above, but the function is also given a name. You want to avoid these with IE8 and earlier, since IE will actually get it quite wrong, creating two separate functions (at two different times). (Basically, IE treats it as both a function declaration and a function expression.) IE9 finally gets this right.
Note that your second and third examples rely on automatic semicolon insertion; because those are both assignment statements, they should end with a ; (after the ending } of the function).

Which JS function-declaration syntax is correct according to the standard?

var foo = function(){ return 1; };
if (true) {
function foo(){ return 2; }
}
foo(); // 1 in Chrome // 2 in FF
//I just want to be sure, is FF 4 not "standard" in this case?
Edit:
what if we have this:
var foo = function(){ return 1; };
if (true) function foo(){ return 2; }
foo(); // is 1 standard or is 2 standard?
The original poster's code isn't permitted by the ECMAScript standard. (ECMAScript the official name for the JavaScript language specification, for legal reasons.) It is, however, a common extension to the language—one which is, unfortunately, implemented differently in different browsers.
In standard JavaScript, function definitions may only occur in top level code, or at the top level of a function's body. You can't have conditionals, loops, or even curly braces between the enclosing function's body and the the function definition.
For example, this is permitted:
function f() {
function g() {
...
}
}
but this is not:
function f() {
{
function g() {
...
}
}
}
What complicates the picture is that most browsers do accept this latter code, but each assigns its own idiosyncratic interpretation to it. Firefox treats it like:
function f() {
{
var g = function g() {
...
}
}
}
The ECMAScript committee is considering choosing a specific interpretation for these "function statements" (as opposed to function definitions). They haven't made a decision yet. Mozilla is discussing its preferred solution here.
The code in the question is not actually allowed at all by current ECMAScript syntax (as of ECMAScript 5). You can do var foo = function() {} inside a block, but you can only do function foo() {} at the toplevel in functions or scripts.
Currently browsers support the code in the question in incompatible ways because they're all implementing extensions to the core language and they implement different extensions. A fully conforming ECMAScript 5 implementation would actually end up with a SyntaxError when compiling this script.
There are proposals to add the ability to do this sort of thing to ECMAScript, but they're not quite finalized yet.
Both are technically wrong, according to the ECMAScript standard, because function declarations are only allowed at the top level or directly inside other functions. Technically a function declaration inside an if block is a syntax error. Most implementations allow it as in extension, but they interpret it differently.
The reason for the difference is that Chrome is treating the foo "declaration" as a normal function declaration and hoisting it to the beginning of the scope. Firefox (for historical reasons IIRC) only declares the function when the if statement gets executed.
To better demonstrate the difference, you could try running this similar code:
console.log(foo()); // 2 in Chrome, error in FF
var foo = function(){ return 1; };
console.log(foo()); // 1 in both Chrome and FF
if (true) {
function foo(){ return 2; }
}
console.log(foo()); // 1 in Chrome // 2 in FF
Edit: Your second example is exactly the same. JavaScript doesn't have block scope, only function-level and program-level. The "problem" isn't that the function declaration is in a block, it's that it's not a top-level statement.
There is no specified behavior for a function declaration not found at the top level of a program or at the top level of a function body. Or, rather, the specified behavior is a syntax error, because the JavaScript grammar doesn't allow such function declarations. The reason for the different behaviors is that browsers historically have been all over the map here, and they remain so due to existing sites written with browser-specific code paths that make it impossible for anyone to change.
Strict mode prohibits this syntax, for what it's worth, and it's likely a future version of ECMAScript will define it. But for now you should not use it, because its behavior is not precisely defined by specs, and you'll get different behavior in different browsers.
fiddle. This is Undefined Behaviour. It's a mess.
How firefox interprets it is handled by the other answers
How chrome interprets it
var foo = function() { return 1 };
if (true) {
function foo() {
return 2;
}
}
console.log(foo());
What's acctually happening is function foo is being declared then overwritten with a local variable foo immediately.
This gets translated into
function foo() {
return 2;
}
var foo;
foo = function() { return 1 };
if (true) { }
console.log(foo());

whats the difference between function foo(){} and foo = function(){}? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
are they the same? I've always wondered
No, they're not the same, although they do both result in a function you can call via the symbol foo. One is a function declaration, the other is a function expression. They are evaluated at different times, have different effects on the scope in which they're defined, and are legal in different places.
Quoting my answer to this other question here (edited a bit for relevance), in case the other question were ever removed for some reason (and to save people following the link):
JavaScript has two different but related things: Function declarations, and function expressions. There are marked differences between them:
This is a function declaration:
function foo() {
// ...
}
Function declarations are evaluated upon entry into the enclosing scope, before any step-by-step code is executed. The function's name (foo) is added to the enclosing scope (technically, the variable object for the execution context the function is defined in).
This is a function expression (specifically, an anonymous one, like your quoted code):
var foo = function() {
// ...
};
Function expressions are evaluated as part of the step-by-step code, at the point where they appear (just like any other expression). That one creates a function with no name, which it assigns to the foo variable.
Function expressions can also be named rather than anonymous. A named one looks like this:
var x = function foo() { // Valid, but don't do it; see details below
// ...
};
A named function expression should be valid, according to the spec. It should create a function with the name foo, but not put foo in the enclosing scope, and then assign that function to the x variable (all of this happening when the expression is encountered in the step-by-step code). When I say it shouldn't put foo in the enclosing scope, I mean exactly that:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
Note how that's different from the way function declarations work (where the function's name is added to the enclosing scope).
Named function expressions work on compliant implementations, but there used to be several bugs in implementations in the wild, most especially Internet Explorer 8 and earlier (and some early versions of Safari). IE8 processes a named function expresssion twice: First as a function declaration (upon entry into the execution context), and then later as a function expression, generating two distinct functions in the process. (Really.)
More here: Double take and here: Named function expressions demystified
NOTE: The below was written in 2011. In 2015, function declarations in control blocks were added to the language as part of ECMAScript 2015. Their semantics vary depending on whether you're in strict or loose mode, and in loose mode if the environment is a web browser. And of course, on whether the environment you're using has correct support for the ES2015 definition for them. (To my surprise, as of this writing in July 2017, Babel doesn't correctly transpile them, either.) Consequently, you can only reliably use function declarations within control-flow structures in specific situations, so it's still probably best, for now, to use function expressions instead.
And finally, another difference between them is where they're legal. A function expression can appear anywhere an expression can appear (which is virtually anywhere). A function declaration can only appear at the top level of its enclosing scope, outside of any control-flow statements. So for instance, this is valid:
function bar(x) {
var foo;
if (x) {
foo = function() { // Function expression...
// Do X
};
}
else {
foo = function() { // ...and therefore legal
// Do Y
};
}
foo();
}
...but this is not, and does not do what it looks like it does on most implementations:
function bar(x) {
if (x) {
function foo() { // Function declaration -- INVALID
// Do X
}
}
else {
function foo() { // INVALID
// Do Y
}
}
foo();
}
And it makes perfect sense: Since the foo function declarations are evaluated upon entry into the bar function, before any step-by-step code is executed, the interpreter has no idea which foo to evaluate. This isn't a problem for expressions since they're done during the control-flow.
Since the syntax is invalid, implementations are free to do what they want. I've never met one that did what I would have expected, which is to throw a syntax error and fail. Instead, nearly all of them just ignore the control flow statements and do what they should do if there are two foo function declarations at the top level (which is use the second one; that's in the spec). So only the second foo is used. Firefox's SpiderMonkey is the standout, it seems to (effectively) convert them into expressions, and so which it uses depends on the value of x. Live example.
I got an excellent explanation on this while asking very similar question: Two functions with the same name in JavaScript - how can this work?

Named Function Expressions in IE, part 2

I asked this question a while back and was happy with the accepted answer. I just now realized, however, that the following technique:
var testaroo = 0;
(function executeOnLoad() {
if (testaroo++ < 5) {
setTimeout(executeOnLoad, 25);
return;
}
alert(testaroo); // alerts "6"
})();
returns the result I expect. If T.J.Crowder's answer from my first question is correct, then shouldn't this technique not work?
A very good question. :-)
The difference:
The difference between this and your detachEvent situation is that here, you don't care that the function reference inside and outside "the function" is the same, just that the code be the same. In the detachEvent situation, it mattered that you see the same function reference inside and outside "the function" because that's how detachEvent works, by detaching the specific function you give it.
Two functions?
Yes. CMS pointed out that IE (JScript) creates two functions when it sees a named function expression like the one in your code. (We'll come back to this.) The interesting thing is that you're calling both of them. Yes, really. :-) The initial call calls the function returned by the expression, and then all of the calls using the name call the the other one.
Modifying your code slightly can make this a bit clearer:
var testaroo = 0;
var f = function executeOnLoad() {
if (testaroo++ < 5) {
setTimeout(executeOnLoad, 25);
return;
}
alert(testaroo); // alerts "6"
};
f();
The f(); at the end calls the function that was returned by the function expression, but interestingly, that function is only called once. All the other times, when it's called via the executeOnLoad reference, it's the other function that gets called. But since the two functions both close over the same data (which includes the testaroo variable) and they have the same code, the effect is very like there being just one function. We can demonstrate there are two, though, much the way CMS did:
var testaroo = 0;
var f = function executeOnLoad() {
if (testaroo++ < 5) {
setTimeout(executeOnLoad, 0);
return;
}
alert(testaroo); // alerts "6"
// Alerts "Same function? false"
alert("Same function? " + (f === executeOnLoad));
};
f();
This isn't just some artifact of the names, either, there really are two functions being created by JScript.
What's going on?
Basically, the people implementing JScript apparently decided to process named function expressions both as function declarations and as function expressions, creating two function objects in the process (one from the "declaration," one from the "expression") and almost certainly doing so at different times. This is completely wrong, but it's what they did. Surprisingly, even the new JScript in IE8 continues this behavior.
That's why your code sees (and uses) two different functions. It's also the reason for the name "leak" that CMS mentioned. Shifting to a slightly modified copy of his example:
function outer() {
var myFunc = function inner() {};
alert(typeof inner); // "undefined" on most browsers, "function" on IE
if (typeof inner !== "undefined") { // avoid TypeError on other browsers
// IE actually creates two function objects: Two proofs:
alert(inner === myFunc); // false!
inner.foo = "foo";
alert(inner.foo); // "foo"
alert(myFunc.foo); // undefined
}
}
As he mentioned, inner is defined on IE (JScript) but not on other browsers. Why not? To the casual observer, aside from the two functions thing, JScript's behavior with regard to the function name seems correct. After all, only functions introduce new scope in Javascript, right? And the inner function is clearly defined in outer. But the spec actually went to pains to say no, that symbol is not defined in outer (even going so far as to delve into details about how implementations avoid it without breaking other rules). It's covered in Section 13 (in both the 3rd and 5th edition specs). Here's the relevant high-level 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.
Why did they go to this trouble? I don't know, but I suspect it relates to the fact that function declarations are evaluated before any statement code (step-by-step code) is executed, whereas function expressions — like all expressions — are evaluated as part of the statement code, when they're reached in the control flow. Consider:
function foo() {
bar();
function bar() {
alert("Hi!");
}
}
When the control flow enters function foo, one of the first things that happens is that the bar function is instantiated and bound to the symbol bar; only then does the interpreter start processing the statements in foo's function body. That's why the call to bar at the top works.
But here:
function foo() {
var f;
f = function() {
alert("Hi!");
};
f();
}
The function expression is evaluated when it's reached (well, probably; we can't be sure some implementations don't do it earlier). One good reason the expression isn't (or shouldn't be) evaluated earlier is:
function foo() {
var f;
if (some_condition) {
f = function() {
alert("Hi (1)!");
};
}
else {
f = function() {
alert("Hi! (2)");
};
}
f();
}
...doing it earlier leads to ambiguity and/or wasted effort. Which leads to the question of what should happen here:
function foo() {
var f;
bar();
if (some_condition) {
f = function bar() {
alert("Hi (1)!");
};
}
else {
f = function bar() {
alert("Hi! (2)");
};
}
f();
}
Which bar gets called at the beginning? The way the specification authors chose to address that situation was to say that bar is not defined in foo at all, hence side-stepping the issue entirely. (It's not the only way they could have addressed it, but it seems to be the way they chose to do so.)
So how does IE (JScript) process that? The bar called at the beginning alerts "Hi (2)!". This, combined with the fact we know two function objects are created based on our other tests, is the clearest indication that JScript processes named function expressions as function declarations and function expressions, because that's exactly what is supposed to happen here:
function outer() {
bar();
function bar() {
alert("Hi (1)!");
}
function bar() {
alert("Hi (2)!");
}
}
There we have two function declarations with the same name. Syntax error? You'd think so, but it isn't. The specification clearly allows it, and says that the second declaration in source code order "wins." From Section 10.1.3 of the 3rd edition spec:
For each FunctionDeclaration in the code, in source text order, create a property of the variable object whose name is the Identifier in the FunctionDeclaration...If the variable object already has a property with this name, replace its value and attributes...
(The "variable object" is how symbols get resolved; that's a whole 'nother topic.) It's just as unambiguous in the 5th edition (Section 10.5), but, um, a lot less quotable.
So it's just IE, then?
Just to be clear, IE isn't the only browser that has (or had) unusual handling of NFEs, although they're getting pretty lonely (a pretty big Safari issue has been fixed, for instance). It's just that JScript has a really big quirk in this regard. But come to that, I think it actually is the only current major implementation with any really big issue — be interested to know of any others, if anyone knows of them.
Where we stand
Given all of the above, for the moment, I stay away from NFEs because I (like most people) have to support JScript. After all, it's easy enough to use a function declaration and then refer to it later (or indeed, earlier) with a variable:
function foo() { }
var f = foo;
...and that works reliably across browsers, avoiding issues like your detachEvent problem. Other reasonable people solve the problem differently, just accepting that two functions will get created and trying to minimize the impact, but I don't like that answer at all because of exactly what happened to you with detachEvent.
Well, it will work, the problem with JScript (IE), is that the identifier of the function expression (executeOnLoad) will leak to its enclosing scope, and actually creating two function objects..
(function () {
var myFunc = function foo () {};
alert(typeof foo); // "undefined" on all browsers, "function" on IE
if (typeof foo !== "undefined") { // avoid TypeError on other browsers
alert( foo === myFunc ); // false!, IE actually creates two function objects
}
})();

Categories