简体   繁体   English

Function if/else 语句中的声明?

[英]Function declarations inside if/else statements?

How are function declarations handled?如何处理 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'

This example produces different outputs in Chrome and Firefox. Chrome outputs foo while FF outputs 19 .此示例在 Chrome 和 Firefox 中产生不同的输出。Chrome 输出foo而 FF 输出19

When this question was asked, ECMAScript 5 (ES5) was prevalent.当提出这个问题时,ECMAScript 5 (ES5) 很流行。 In strict mode of ES5, function declarations cannot be nested inside of an if block as shown in the question.在 ES5 的严格模式下,function 声明不能嵌套在if块中,如问题中所示。 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.不同的浏览器和引擎针对如何处理块内的 function 声明实施了自己的规则。

As of 2018, many browsers support ECMAScript 2015 (ES2015) to the extent that function declarations are now allowed inside blocks .截至 2018 年,许多浏览器支持 ECMAScript 2015 (ES2015),以至于function 声明现在允许在块内进行 In an ES2015 environment, a function declaration inside of a block will be scoped inside that block.在 ES2015 环境中,块内的 function 声明将在该块内作用域。 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.问题中的代码将导致未定义的 function 错误,因为 function a仅在if语句的 scope 中声明,因此在全局 scope 中不存在。

If you need to conditionally define a function, then you should use function expressions .如果您需要有条件地定义一个 function,那么您应该使用function 表达式

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 声明:

function foo() {
}

and function expression和 function 表达式

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”. “函数声明和 function 变量总是被 JavaScript 解释器移动('提升')到它们的 JavaScript scope 的顶部”。

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 声明function a()被提升到 Javascript scope 的顶部,因此即使 if 评估为 false 也会生成“foo”

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()被解析器解析,在尝试调用alert(foo())之前将foo()放入当前 scope

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).在 JavaScript 执行中有 Context(ECMA 5 将其分解为 LexicalEnvironment、VariableEnvironment 和 ThisBinding)和 Process(一组按顺序调用的语句)。 Declarations contribute to the VariableEnvironment when the execution scope is entered.输入执行 scope 时,声明有助于变量环境。 They are distinct from Statements (such as return) and are not subject to their rules of process.它们与声明(例如退货)不同,并且不受其流程规则的约束。

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. ECMA-262 v5 要求实现在进入任何新的全局或函数级执行上下文时在第一遍期间注册所有 function 和变量声明。 Chrome is technically doing it right here because it is looking inside the else and then blocks and registering a() prior to execution. Chrome 在技术上就是在这里做的,因为它正在查看else的内部, then在执行之前阻止并注册a() Unfortunately it produces the most unreadable results.不幸的是,它会产生最难读的结果。

FF is waiting until it evaluates the if statement before it evaluates and adds function and variable declarations to the current context. FF 会一直等到它对 if 语句进行求值,然后再求值并将 function 和变量声明添加到当前上下文中。 BTW.顺便提一句。 Both browsers do it this way inside catch and finally clauses.两种浏览器在 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.这实际上只是两个不同的 ECMA 实现处理一个不应该出现的特性的问题。 The scenario at hand shows why function declarations shouldn't be inside control flow statements.手头的场景显示了为什么 function 声明不应该在控制流语句中。

Function declarations are not accessible outside {} blocks. Function 声明在{}块之外是不可访问的。

if (true) {
  function sayHi() {
    alert("hii");
  }
  sayHi(); //accessible
}

sayHi(); //error, not accessible since out of the block

If you want to define conditional functions, use function expressions like如果要定义条件函数,请使用 function 表达式,例如

let sayHi;
if (true) {
  sayHi = function(){
    alert("hii");
  }
  sayHi(); //accessible
}

sayHi(); //accessible

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM