4

Although I couldn't find a reference to this easily in google, I'm familiar with the fact that, in javascript, global function declarations get interpreted before any code is executed. In other words, this works fine:

f();
function f() {}

However, I've noticed that chrome and firefox have different interpretations of what a global function declaration is. In particular, chrome is happy reading a function declaration that is inside an if block in the first pass, but firefox is not.

try {document.write(f);}               // works in chrome
catch(e) {document.write(e.message);}  // throws an error in firefox

try {document.write(g);}               // works in chrome and firefox
catch(e) {document.write(e.message);}

if(true) function f() {}
function g() {}

You can try this example yourself with this fiddle. I'm using Chrome 16.0.912.75 and Firefox 9.0.1.

What is the ECMA standard for this behavior? Is there a term for this process of "lifting" function declarations above other code? Is what code gets "lifted" open to interpretation (are both browsers right)? Or is it a bug in one of them?

Chris
  • 6,805
  • 3
  • 35
  • 50
  • More info here: [If functions in JS are first-class, what allows them to be called before they are defined?](http://stackoverflow.com/questions/12274014/if-functions-in-js-are-first-class-what-allows-them-to-be-called-before-they-ar) – Brent Bradburn Oct 05 '13 at 19:24
  • 3
    Adding [`"use strict"`](http://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it) at the top of your code will normalize the behavior. – Brent Bradburn Oct 05 '13 at 19:26

2 Answers2

11

This answer is outdated since the release of ES6 in 2015. See What are the precise semantics of block-level functions in ES6? for how it works since then.


Function declarations are not valid in blocks. You have undefined behaviour which is undefined.

Function declarations at a top level (either global or top level within a function) are hoisted.

Function declarations inside blocks are a syntax error in strict mode

(function () { 
  "use strict"; 
  if (true) { 
    function g() { } 
  } 
})();

SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • Ok, well then why does Chrome swallow them so blithely? – Chris Jan 15 '12 at 18:03
  • Who knows? Submit a bug report. – Greg Hewgill Jan 15 '12 at 18:03
  • @Chris I don't the reasons about why Chrome and Firefox implement this undefined behaviour in an implementation specific manner. However it can't be removed anymore because that would break backwards compatibility with the internet – Raynos Jan 15 '12 at 18:05
  • Actually, the spec defines the behavior here: it's defined to be a SyntaxError. That just happens to not be web-compatible. – Boris Zbarsky Jan 16 '12 at 05:33
  • 1
    I found this to be a disturbing limitation of JavaScript -- and surprising since functions are first-class objects. Then I realized that that functions can be declared inside blocks, but it requires a different syntax: `var g = function() {}` – Brent Bradburn Oct 05 '13 at 19:30
0

The ECMA standard for this behavior is to throw a SyntaxError when parsing the script. Unfortunately doing that is not compatible with the web as Raynos says.

See Which JS function-declaration syntax is correct according to the standard? for some extended discussion on the issue.

Community
  • 1
  • 1
Boris Zbarsky
  • 34,758
  • 5
  • 52
  • 55