Javascript if/else 语句中的函数声明?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10069204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Function declarations inside if/else statements?
提问by HellaMad
How are function declarations handled?
如何处理函数声明?
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'
This example produces different outputs in Chrome and Firefox. Chrome outputs foo
while FF outputs 19
.
此示例在 Chrome 和 Firefox 中生成不同的输出。Chrome 输出foo
而 FF 输出19
。
回答by Cheran Shunmugavel
When this question was asked, ECMAScript 5 (ES5) was prevalent. In strict mode of ES5, function declarations cannot be nested inside of an if
block as shown in the question. In non-strict mode, the results were unpredictable. Different browsers and engines implemented their own rules for how they would handle function declarations inside blocks.
当提出这个问题时,ECMAScript 5 (ES5) 很流行。在 ES5 的严格模式下,函数声明不能嵌套在if
块内,如问题所示。在非严格模式下,结果是不可预测的。不同的浏览器和引擎针对如何处理块内的函数声明实施了自己的规则。
As of 2018, many browsers support ECMAScript 2015 (ES2015) to the extent that function declarations are now allowed inside blocks. In an ES2015 environment, a function declaration inside of a block will be scoped inside that block. The code in the question will result in an undefined function error because the function a
is only declared within the scope of if
statements and therefore doesn't exist in the global scope.
截至 2018 年,许多浏览器都支持 ECMAScript 2015 (ES2015),以至于现在允许在 blocks 中声明函数。在 ES2015 环境中,块内的函数声明将限定在该块内。问题中的代码将导致未定义函数错误,因为该函数a
仅在if
语句范围内声明,因此不存在于全局范围内。
If you need to conditionally define a function, then you should use function expressions.
如果你需要有条件地定义一个函数,那么你应该使用函数表达式。
回答by Andreas Wong
From http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
来自http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
In javascript, you have function declaration:
在 javascript 中,你有函数声明:
function foo() {
}
and function expression
和函数表达式
var foo = function() {
}
Quoting from http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
引自http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
“Function declarations and function variables are always moved (‘hoisted') to the top of their JavaScript scope by the JavaScript interpreter”.
“函数声明和函数变量总是被 JavaScript 解释器移动('提升')到它们的 JavaScript 范围的顶部”。
So what happened in your first example is that function declaration of function a()
, gets hoisted to the top of the Javascript scope, thus producing 'foo' even though the if evaluates to false
所以在你的第一个例子中发生的事情是 , 的函数声明function a()
被提升到 Javascript 范围的顶部,从而产生 'foo' 即使 if 评估为 false
Think of var foo
as a normal Javascript statement, it's only executed on the runtime of your javascript, unlike function foo()
, that's why the below is valid:
将其var foo
视为普通的 Javascript 语句,它仅在您的 javascript 运行时执行,与 不同function foo()
,这就是以下内容有效的原因:
alert(foo());
function foo() {
return 'gw ganteng';
}
Here, function foo()
is parsed by the parser, putting foo()
in the current scope, before attempting to call alert(foo())
在这里,function foo()
由解析器解析,放入foo()
当前范围,然后再尝试调用alert(foo())
http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
In JavaScript execution there is Context (which ECMA 5 breaks into LexicalEnvironment, VariableEnvironment and ThisBinding) and Process (a set of statements to be invoked in sequence). Declarations contribute to the VariableEnvironment when the execution scope is entered. They are distinct from Statements (such as return) and are not subject to their rules of process.
在 JavaScript 执行中有 Context(ECMA 5 将其分解为 LexicalEnvironment、VariableEnvironment 和 ThisBinding)和 Process(一组要按顺序调用的语句)。当进入执行范围时,声明会影响 VariableEnvironment。它们与声明(例如退货)不同,并且不受其流程规则的约束。
回答by drankin2112
The ECMA-262 v5 requires implementations to register all function and variable declarations during the first pass when entering any new global or function-level execution context. Chrome is technically doing it right here because it is looking inside the else
and then
blocks and registering a()
prior to execution. Unfortunately it produces the most unreadable results.
ECMA-262 v5 要求实现在第一次进入任何新的全局或函数级执行上下文时注册所有函数和变量声明。从技术上讲,Chrome 正在这里做这件事,因为它在执行之前查看else
和then
阻止并注册a()
。不幸的是,它产生了最不可读的结果。
FF is waiting until it evaluates the if statement before it evaluates and adds function and variable declarations to the current context. BTW. Both browsers do it this way inside catch and finally clauses.
FF 等待直到它评估 if 语句,然后才会评估并将函数和变量声明添加到当前上下文。顺便提一句。两个浏览器都在 catch 和 finally 子句中这样做。
It really is just a matter of two different ECMA implementations dealing with a feature that shouldn't be there to begin with. The scenario at hand shows why function declarations shouldn't be inside control flow statements.
这实际上只是两个不同的 ECMA 实现处理一个不应该存在的特性的问题。手头的场景说明了为什么函数声明不应该在控制流语句中。