Why is a function declaration in a condition block designed to work in Chrome but not in Firefox?

Why do the following codes give different results between Chrome and Firefox?

f = function() {return true;}; g = function() {return false;}; (function() { if (g() && [] == ![]) { f = function f() {return false;}; function g() {return true;} } })(); console.log(f()); 

In Chrome: the result is false . However, in Firefox, this is true .

The key line of the above codes is line 4, and based on my knowledge of raising the function name, the function g should be on line 6, namely line 2 is redefined by line 6. IMO, the behavior of Chrome is correct.

I'm right? if so, why is Firefox displaying different results?

+11
javascript firefox google-chrome
Aug 04 '14 at 2:37
source share
1 answer

ECMAScript 5, the current official JavaScript specification, does not define behavior for function declarations within blocks.

Kangax Quote:

The Declarations function is only allowed in Program or FunctionBody. Syntactically, they cannot be displayed in a block ( { ... } ) - for example, in if , while or for expressions. This is because Blocks can only contain expressions, not SourceElements, which are FunctionDeclaration. If we carefully consider the production rules, we will see that the only way of expression allowed directly in the block is when it is part of the ExpressionStatement. However, the ExpressionStatement expression is explicitly defined so as not to start with the keyword “function” , and that is why FunctionDeclaration cannot be displayed directly in Statement or Block (note that Block is just a list of statements).

Due to these limitations, whenever a function appears directly in a block (for example, in the previous example), it should be considered a syntax error , not a function declaration or expression. The problem is that almost none of the implementations I've seen analyzes these functions strictly according to the rules (exceptions are BESEN and DMDScript). Instead, they interpret them proprietary.

It is also worth quoting the ECMAScript 6 project - B.3.3. Block level function declarations. Web compatibility. Compatibility Semantics :

Until the sixth edition, the ECMAScript specification did not define the appearance of FunctionDeclaration as an element of the Statement StatementList block. However, support for this form of FunctionDeclaration was a valid extension, and most ECMAScript-enabled versions of the browser allowed them. Unfortunately, the semantics of such declarations are different from these implementations. [...]




Since ES5 does not define behavior for function declarations within blocks, allowing the use of proprietary extensions, there are technically no “rights” or “wrong” ones. Consider their "unspecified behavior" that cannot be tolerated in different ES5 compatible environments.

In any case, they are easy to rewrite into portable code:

  • Should a function declaration be raised at the top of the current function / global area? Make sure the function declaration is not directly inside the block.
  • Should a function be declared only when a block is executed? Assign the function expression to the variable ( var f = function() {}; ). Note that there is no lifting, and the variable is still accessible outside the block ( var declarations are areas with a functional level).



According to ECMAScript 6, function declarations are block-limited, which is why Firefox implements the right behavior ES6-wise.

+15
Aug 04 '14 at 2:59
source share



All Articles