if/else语句中的函数声明?

DC_*_*DC_ 48 javascript scope function

如何处理函数声明?

var abc = '';
if(1 === 0){
    function a(){
        abc = 7;
    }
}else if('a' === 'a'){
    function a(){
        abc = 19;
    }
}else if('foo' === 'bar'){
    function a(){
        abc = 'foo';
    }
} 
a();
document.write(abc); //writes "foo" even though 'foo' !== 'bar'
Run Code Online (Sandbox Code Playgroud)

此示例在Chrome和Firefox中生成不同的输出.fooFF输出时输出Chrome 19.

Che*_*vel 58

当提出这个问题时,ECMAScript 5(ES5)很普遍.在ES5的严格模式下,函数声明不能​​嵌套在if块内,如问题所示.在非严格模式下,结果是不可预测的.不同的浏览器和引擎实现了他们自己处理块内函数声明的规则.

截至2018年,许多浏览器都支持ECMAScript 2015(ES2015),现在允许在块内部使用函数声明.在ES2015环境中,块内的函数声明将作用于该块内.问题中的代码将导致未定义的函数错误,因为该函数a仅在if语句范围内声明,因此在全局范围内不存在.

如果需要有条件地定义函数,那么应该使用函数表达式.


And*_*ong 7

来自http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

在javascript中,你有函数声明:

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

和函数表达式

var foo = function() {
}
Run Code Online (Sandbox Code Playgroud)

引自http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

"函数声明和函数变量总是由JavaScript解释器移动('提升')到JavaScript范围的顶部".

所以在你的第一个例子中发生的是,函数声明function a()被提升到Javascript范围的顶部,因此产生'foo',即使if计算结果为false

可以认为var foo是一个普通的Javascript语句,它只在你的javascript的运行时执行,不像function foo(),这就是为什么以下是有效的:

alert(foo());

function foo() {
   return 'gw ganteng';
}
Run Code Online (Sandbox Code Playgroud)

这里,在尝试调用之前function foo(),由解析器解析,放入foo()当前作用域alert(foo())

http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

在JavaScript执行中,有Context(ECMA 5分为LexicalEnvironment,VariableEnvironment和ThisBinding)和Process(一组要按顺序调用的语句).输入执行范围时,声明对VariableEnvironment有贡献.它们与陈述(例如退货)不同,不受其程序规则的约束.