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

前端 未结 5 470
走了就别回头了
走了就别回头了 2020-12-10 03:39
  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 \"s         


        
相关标签:
5条回答
  • 2020-12-10 04:03

    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.

    0 讨论(0)
  • 2020-12-10 04:09

    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.

    0 讨论(0)
  • 2020-12-10 04:10

    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.

    0 讨论(0)
  • 2020-12-10 04:11

    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());
    
    0 讨论(0)
  • 2020-12-10 04:21

    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.

    0 讨论(0)
提交回复
热议问题