Ram*_*mar 6 javascript var function redeclaration hoisting
如果我们声明一个变量和一个具有相同名称的函数,则它接受重新声明。但是,当我们在一个块内执行相同的操作时,它会显示重新声明错误。
码:
var x;
function x() {}; // no error.但是在这种情况下,我得到了错误。
{
  var inside; // re-declaration error.
  function inside() {};
}预期结果应该没有错误。
这是 EcmaScript 6 的更改。从 ES6 开始,不再允许在块作用域内有重复的绑定。
13.2.1 静态语义:早期错误
块:{语句列表}
如果StatementList的 LexicallyDeclaredNames包含任何重复条目,则这是一个语法错误。
如果StatementList的 LexicallyDeclaredNames 的任何元素也出现在StatementList的 VarDeclaredNames 中,则为语法错误。
第一部分是相关的 -LexicallyDeclaredNames包含块内代码中找到的所有声明。
据推测,这是 ES6 中函数声明语义变化的一部分,因为现在它们可以是块作用域的:
{ //block 1
  function foo() { // declared in block 1
    return 1;
  }
  console.log("block 1: foo() === 1", foo() === 1);
  
  { // block 2
    function foo() { // declared in block 2
      return 2;
    }
    console.log("block 2: foo() === 2", foo() === 2);
  }
  
  console.log("block 1: foo() === 1", foo() === 1);
}这是等效 ES5 代码的语法糖:
(function() { //block 1
  var foo = function() {
    return 1;
  }
  console.log("block 1: foo() === 1", foo() === 1);
  (function() { //block 2
    var foo = function() {
      return 2;
    }
    console.log("block 2: foo() === 2", foo() === 2);
  })();
  console.log("block 1: foo() === 1", foo() === 1);
})();但是,此功能无法处理重复的名称。
对于任何块,包括其他类型的块语句,都存在相同的行为。这是一个例子:
{ //block
  function foo() { return 1; }
  console.log("block: foo() === 1", foo() === 1);
  
  if (true) { // if block
    function foo() { return 2; }
    console.log("if block: foo() === 2", foo() === 2);
  }
  
  for (var i = 0; i < 1; i++) { // for block
    function foo() { return 3; }
    console.log("for block: foo() === 3", foo() === 3);
  }
  
  switch ("hello world") { // case block
    default:
      function foo() { return 4; }
      console.log("case block: foo() === 4", foo() === 4);
  }
  
  console.log("block: foo() === 1", foo() === 1);
}但是,应该注意的是,相同类型(var或function)的重复声明不会导致错误:
{
  var foo = 1;
  var foo = 2;
  
  console.log("foo ->", foo);
}
{
  function bar() { return "a"; }
  function bar() { return "b"; }
  
  console.log("bar() ->", bar());
}因此,它们似乎没有被视为不同的声明,而是覆盖了相同的词法声明名称。
小智 0
在进一步探索这一点时,我遇到了这个: https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError
有趣的是,对于这种情况,我的结果与他们的不同:
    try{
        eval(`{
            var x;
            function x(){};
        }`);
    }catch(e){
        console.log(e instanceof SyntaxError);
        console.log(e.message);                // "Hello"
        console.log(e.name);                   // "SyntaxError"
        console.log(e.fileName);               // "someFile.js"
        console.log(e.lineNumber);             // 10
        console.log(e.columnNumber);           // 0
        console.log(e.stack);                  // "@Scratchpad/2:11:9\n"
    }
结果:
true // instanceof SyntaxError
06:01:10.526 VM3194:22 Identifier 'x' has already been declared // e.message
06:01:10.527 VM3194:23 SyntaxError // e.name
06:01:10.527 VM3194:24 undefined   // e.filename
06:01:10.527 VM3194:25 undefined   // e.lineNumber
06:01:10.527 VM3194:26 undefined   // e.columnNumber
06:01:10.527 VM3194:27 SyntaxError: Identifier 'x' has already been declared at VM3194:16 // e.stack