Javascript命名的函数定义在不应该执行时执行

BIO*_*IOS 5 javascript

我不知道这里发生了什么.代码是:

  if( true ) { 

      console.log('In first function definition');

      function test(){
        console.log('Hello world');
      }

    } else {

      console.log('In the second function definition');

      function test(){
        console.log('Goodbye world');
      }

    }

  test();
Run Code Online (Sandbox Code Playgroud)

我希望这会登录控制台:

'In the first function definition'
'Hello world'
Run Code Online (Sandbox Code Playgroud)

但相反它记录:

'In the first function definition'
'Goodbye world'
Run Code Online (Sandbox Code Playgroud)

当代码没有进入该分支时,如何创建第二个命名函数?

Ada*_*kis 10

请记住,JavaScript中的所有内容都是功能范围的; 没有块范围.

为此,您在同一范围内定义了两个函数声明(无论if-else所在的范围),具有相同的名称,在不同的块中.这会在浏览器之间产生不一致的结果

您需要为这些函数指定不同的名称,或使用函数表达式,如下所示:

var f;
if(true) { 
   console.log('In first function definition');

   f = function(){
     console.log('Hello world');
   };

} else {
  console.log('In the second function definition');

  f = function(){
    console.log('Goodbye world');
  };
}
f();
Run Code Online (Sandbox Code Playgroud)

对你的优秀问题

但是如果我们不输入代码的那个分支,那么函数是如何定义的呢?如果没有执行该块,为什么要考虑范围?

简单的答案是函数声明被"提升",并且即使在声明本身之前,也可以立即在范围内的任何位置使用.

即:

function foo(){
    f(); //perfectly valid

    function f(){
    }
}
Run Code Online (Sandbox Code Playgroud)

更长的答案是,在进入范围之前,所有变量声明和函数声明都被删除,并放在"激活对象"上.然后将激活对象放置在"范围链"的头部.执行该函数时,只需从那里解析对这些变量和函数的任何引用.

  • +1 - 函数表达式是一致结果的关键.有些浏览器允许条件声明(例如Firefox),但其他浏览器不允许(例如IE).使用表达式提供一致的结果 (2认同)
  • @AdamRackis:*"因此规范在同一范围内具有相同名称的多个函数声明具有正确定义的行为?"*是:当同一范围内有多个声明时,最后一个声明获胜; [第10.5节](http://bit.ly/11k8r7u)明确了这一点.但上面的声明**无效**因为它们处于条件块中,这是不允许的.[第12节](http://bit.ly/15zQ2H8)甚至特别指出了这一点.有些引擎可以容忍它们,但它们彼此不一致(甚至是它们自己的早期版本). (2认同)