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

Javascript if/else语句中的函数声明?,javascript,function,scope,Javascript,Function,Scope,如何处理函数声明 var abc=”; 如果(1==0){ 函数a(){ abc=7; } }else if('a'='a'){ 函数a(){ abc=19; } }否则如果('foo'=='bar'){ 函数a(){ abc=‘foo’; } } a(); 文件写作(abc)//写“foo”,即使是“foo”!='条“自 在javascript中,有函数声明: function foo() { } 和函数表达式 var foo = function() { } 引用 “函数声明和函数变量

如何处理函数声明

var abc=”;
如果(1==0){
函数a(){
abc=7;
}
}else if('a'='a'){
函数a(){
abc=19;
}
}否则如果('foo'=='bar'){
函数a(){
abc=‘foo’;
}
}
a();
文件写作(abc)//写“foo”,即使是“foo”!='条“

在javascript中,有函数声明:

function foo() {
}
和函数表达式

var foo = function() {
}
引用

“函数声明和函数变量始终处于移动状态 ('highed')到JavaScript作用域的顶部 翻译”

因此,在第一个示例中发生的是
函数a()
的函数声明被提升到Javascript范围的顶部,从而产生“foo”,即使if的计算结果为false

var foo
看作一个普通的Javascript语句,它只在Javascript的运行时执行,与
function foo()
不同,这就是为什么下面的语句是有效的:

alert(foo());

function foo() {
   return 'gw ganteng';
}
在这里,
函数foo()
由解析器解析,在尝试调用
警报(foo())
之前,将
foo()
放在当前范围内

在JavaScript执行中存在上下文(ECMA5将其分解为 词汇环境、可变环境和此绑定)和流程 (按顺序调用的一组语句)。声明 当执行范围为 进入。它们与语句(如return)不同,是 不受其程序规则的约束


当提出这个问题时,ECMAScript 5(ES5)非常流行。在ES5的严格模式下,函数声明不能嵌套在
if
块中,如问题所示。在非严格模式下,结果是不可预测的。不同的浏览器和引擎实现了各自的规则,用于处理块内的函数声明

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


如果需要有条件地定义函数,则应使用。

ECMA-262 v5要求实现在输入任何新的全局或函数级执行上下文的第一次过程中注册所有函数和变量声明。从技术上讲,Chrome就是在这里做这件事的,因为它正在查看
else
内部,然后
阻塞并在执行之前注册
a()
。不幸的是,它产生了最不可读的结果

FF在对if语句求值并将函数和变量声明添加到当前上下文之前一直在等待,直到它对if语句求值为止。顺便说一句,两种浏览器在catch和finally子句中都是这样做的

这实际上只是两个不同的ECMA实现处理一个本不应该出现的特性的问题。当前的场景显示了为什么函数声明不应该在控制流语句中。

函数声明在
{}
块之外是不可访问的。 如果要定义条件函数,请使用函数表达式,如
我得到了
19
。你使用的是什么引擎?jsfiddle:@DC_389;:链接在我的控制台(firefox)中为我提供了
19
。+1:确认chrome和firefox产生不同的输出。所有引擎在这里都正常工作。Chrome等人直接通过规范工作,FF的行为是规范的扩展,即设计不同。本质上(即chrome)提升是执行的,最后一次声明获胜,但FF实现了他们所称的函数语句(iirc术语),允许对声明进行评估。是的,我认为这里的关键是函数与表达式。您是否有任何引用指定行为应该是什么?@IgnacioVazquez Abrams考虑到提升和执行流,最后一个声明应该占上风。最后,有人做对了。做得好!可能值得一提的是谁实现了什么(即几乎每个人都遵循ES建议save SpiderMonkey)。问题中的第一个示例不是合法语法的说法是错误的,请阅读davin的评论(这是正确的)。函数语句是Mozilla浏览器的合法扩展。@RobG:不,答案是正确的,根据ECMAScript-262规范,第一个示例是不合法的,因为只有语句可以出现在块中,函数声明不是语句(扩展不是标准的,也不是可移植的)。@Jesse规范允许扩展,Mozilla已经选择允许在块中使用FunctionStatement(ECMA-262没有描述)。因此,这不是错误,而是规范允许的故意扩展。这当然不是语法错误,而且据我所知,没有UA在遇到错误时抛出错误,他们只是根据是否将其视为FunctionDeclaration或FunctionStatement来处理它。@Tina,我需要更新或删除此答案。ES2015允许在块内进行函数声明。
if (true) {
  function sayHi() {
    alert("hii");
  }
  sayHi(); //accessible
}

sayHi(); //error, not accessible since out of the block
let sayHi;
if (true) {
  sayHi = function(){
    alert("hii");
  }
  sayHi(); //accessible
}

sayHi(); //accessible