1

So I was making a fiddle and noticed I was getting different results, one was no error, and the other was about an undefined function depending on the browser.

In Chrome it was perfectly functional and worked fine, but in Firefox it gave undefined function.

This is the fiddle i used :

http://jsfiddle.net/98a45Lk9/ - click in the canvas, and check dev tools in Chrome and Firefox.

For me in Chrome i get : test In Firefox i get : ReferenceError: update is not defined

Why do these browsers process JavaScript differently, given they seem to produce different results they must have different rules?

I do not know the results for other browsers such as IE and Opera.

user2864740
  • 60,010
  • 15
  • 145
  • 220
Sir
  • 8,135
  • 17
  • 83
  • 146
  • What's `update` supposed to be? – Pointy Sep 22 '15 at 03:05
  • It's just a function that does `something` either way its defined in one browser, undefined in another.. I don't understand the inconsistency. Why does it occur. – Sir Sep 22 '15 at 03:06
  • Well if it's undefined then it's undefined. What do you expect `update` to do? If there's nothing in a standard that says there's supposed to be an `update` method on the `window` object, then it's just an implementation variation between browsers. – Pointy Sep 22 '15 at 03:07
  • Huh? Its just a function i named update, and it console .logs the word `test`. Does it matter what is in the function, you can see it in the fiddle. It could add numbers together or what ever. What i am asking is why chrome considers it defined and console logs as intended, but firefox decides to handle it very differently. – Sir Sep 22 '15 at 03:10
  • http://stackoverflow.com/questions/5758042/which-js-function-declaration-syntax-is-correct-according-to-the-standard?lq=1 , http://stackoverflow.com/questions/10069204/function-declarations-inside-if-else-statements?lq=1 – user2864740 Sep 22 '15 at 03:30

1 Answers1

4

The code is using a FunctionDeclaration outside of a top-level statement (see SourceElement) and are thus invoking Browser-Defined Behavior.

Per the ECMAScript Grammar the 'correct' solution would be to throw a SyntaxError, but due to implementations accepting the construct this is relaxed to merely a note in the specification.

NOTE Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable difference, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered. Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context.

In summary:

function f () {
   function g() {} /* FunctionDeclaration as SourceElement - OK! */
}

function f () {
    if (x) {
       function g() {} /* FunctionDeclaration as Statement;
                          Browser-defined behavior */
    }
}

function f () {
    var g;
    if (x) {
        g = function () {} /* FunctionExpression - OK! */
    }
}

In Strict Mode, Firefox throws a SyntaxError:

[In Firefox] SyntaxError: in strict mode code, functions may be declared only at top level or immediately within another function

Neither Chrome (45) nor IE (11) follow this optional behavior.

This prohibition isn't strict mode proper, because such function statements are an extension of basic ES5. But it is the - "Don't Pollute Strict Mode with Non-standard Declaration Forms" - recommendation of the ECMAScript committee, and [Firefox wil] implement it.

user2864740
  • 60,010
  • 15
  • 145
  • 220
  • Ah so i have to declare the variable at the top then assign the function to the variable. Damn, Chrome has lead me down a path of messy habits for allowing me to get away with it! – Sir Sep 22 '15 at 03:21
  • @Dave Depends on the correct scope of the function-variable. If it should be a local variable then `var` can be placed *anywhere* in the function. Variable hoisting is well-defined across implementations (so it would have been *exactly equivalent* to write it as `function f () { if (x) { var g = .. } }` or `function f () { if (x) {g = .. }; var g }`, but I try to avoid having variable hoisting occur "around" logic code. This is *technically* a "preference" thing. – user2864740 Sep 22 '15 at 03:22
  • I was referring to the third example, where by the variable `g` scope spans all the code inside function `f`. Otherwise the function would only have the scope defined inside the if statement's curly braces. – Sir Sep 22 '15 at 03:25
  • @Dave Nope! Search for 'variable hoisting'. Functions in JavaScript (ES5) have exactly *one* scope context and *every* `var` inside a function, whether or not it is even evaluated code, applies to that scope. ES6 introduces [`let` with 'more traditional' rules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let). – user2864740 Sep 22 '15 at 03:25
  • Hmm should i adopt ES6 yet or might it be too soon? Also why does Chrome allow this at least from how i see it "sloppy" programming ? – Sir Sep 22 '15 at 03:44
  • @Dave Variable hoisting is just how JavaScript works. Nothing to do with Chrome. As for a FunctionDeclaration as above, the behavior is no more or less correct in Chrome than any other implementation - the 'most correct' behavior would be a SyntaxError (Safari, Chrome, FF and IE all fail this 'most correct' approach; and since whatever they do after that is not covered they are all as 'correct' as each other). As far as ES6, it's definitely too early for general browser use (but can be used in a more controlled environment) and there are ES6 Transpilers available. It is coming, eventually. – user2864740 Sep 22 '15 at 04:10
  • @Dave You may be interested in [Strict Mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) which *may* make some browsers reject the FunctionDeclaration-as-Statement construct. – user2864740 Sep 22 '15 at 04:15
  • Thank you for the information, I will look into it. – Sir Sep 22 '15 at 19:02