注释:请参阅答案末尾的更新,块中的声明变为有效(但如果不使用严格模式,则相当复杂)。
原因如下:
var任意;如果(某些条件){whatever=函数(){//做点什么};}其他{whatever=函数(){//做点别的};}whatever();
您可能会在库的初始化中看到这样的代码,该库必须处理实现差异(例如web浏览器之间的差异、a'la IE的差异附件事件
与标准相比添加事件侦听器
). 不能对函数声明执行等效操作:
如果(某些条件){函数whatever(){//<===不要这样做//做点什么}}其他{函数whatever(){//<===无效//做点别的}}whatever();
…它们没有在控制结构中指定,因此允许JavaScript引擎做它们想做的事情,不同的引擎做了不同的事情。(编辑:同样,请参阅下面的注释,它们现在已指定。)
另外,在
var whatever=函数(){// ...};
和
函数whatever(){// ...}
第一个是函数表达式,当代码在逐步执行上下文(例如,它所在的函数或全局代码的逐步执行)中达到该点时,将对其进行评估。它还导致匿名的函数(引用它的变量有一个名称,但函数没有,这意味着帮助您的工具帮助您).
第二个是函数声明,并在进入上下文时进行评估,之前执行任何循序渐进的代码。(有人将此称为“提升”,因为源代码中更低的部分发生的时间早于源代码中更高的部分。)该函数也有一个合适的名称。
因此,请考虑:
函数foo(){做某事();doSomethingElse();console.log(“typeof bar=”+typeof bar);//记录“功能”功能栏(){}}
然而
函数foo(){做某事();doSomethingElse();console.log(“typeof bar=”+typeof bar);//日志“未定义”var bar=函数(){};}
在第一个示例中,使用声明处理声明之前这个做点什么
并运行其他逐步代码。在第二个示例中,因为它是一个表达,它作为逐步代码的一部分执行,因此函数没有在上面定义(变量在上面定义,因为无功功率,无功功率
也被“吊起”).
收尾:目前,你不能在一般的客户端web中做到这一点:
var bar=function foo(){//<===暂时不要在客户端代码中这样做// ...};
你应该能够做到这一点,这被称为命名函数表达式它是一个函数表达式,为函数提供了一个合适的名称。但各种JavaScript引擎在不同的时间都犯了错误IE直到最近才真正犯了错误.
ES2015更新+
从ES2015(也称为“ES6”)开始,块内的函数声明被添加到规范中。
严格模式
在严格模式下,新指定的行为简单易懂:它们被限定到发生它们的区块,并被提升到区块顶部。
所以这个:
“使用严格”;如果(Math.random()<0.5){foo();函数foo(){console.log(“低”);}}其他{foo();函数foo(){console.log(“高”);}}console.log(foo类型);//未定义
(注意调用函数的方式在上面块中的函数。)
…本质上等同于:
“使用严格”;if(数学随机数()<0.5){让foo=function(){console.log(“低”);};foo();}其他{让foo=function(){console.log(“高”);};foo();}console.log(foo类型);//未定义
松散模式
松散模式行为要复杂得多,而且理论上它在web浏览器中的JavaScript引擎和JavaScript引擎之间有所不同不在web浏览器中。我不会在这里介入。不要这样做。如果你坚持在块中声明函数,那么使用严格模式,在这种模式下,函数声明是有意义的,并且在不同的环境中是一致的。