【问题标题】:Is a function hoisted if it is defined within an if condition?如果在 if 条件中定义函数,它是否会被提升?
【发布时间】:2015-10-18 06:50:12
【问题描述】:

所以假设我有这样的东西

var x = 1;
   if (function f(){}) {
     x += typeof f;
   }
   x;

这会输出“1undefined”。我认为它应该输出“1function”,因为函数 f(){} 应该被提升到 if 之上。显然不是这样——为什么?我认为函数声明和主体总是被提升到范围的顶部?

【问题讨论】:

标签: javascript hoisting


【解决方案1】:

函数声明被提升。函数表达式are not.

这会创建一个命名的函数表达式:

if(function f(){})

除了检查函数表达式是否为真之外,它什么也不做。 (函数表达式总是真实的。)

关于命名函数表达式,见https://kangax.github.io/nfe/#named-expr:

要记住的一个重要细节是,此名称仅在 新定义函数的作用域

这段代码在新函数表达式的范围之外,因此f是未定义的:

x += typeof f;

一个命名函数表达式中,你可以毫无问题地引用它的名字:

(function f() {
  alert(typeof f);   //function
})();

alert(typeof f);     //undefined

【讨论】:

  • 我认为toString 不相关。函数是对象类型,是converted to true in boolean contexts
  • 这里要理解的一个关键是function f(){} 本身就是一个函数声明(它会被提升)。但是用括号括起来使它成为一个函数表达式(它没有被提升),因为那个分组运算符(括号)只能包含一个表达式。
【解决方案2】:

据我所知,ES5 并未定义块内函数声明的行为。

引用Kangax:

FunctionDeclarations 只允许出现在 Program 或 功能体。从语法上讲,它们不能出现在块中 ({ ... }) — 例如 if、while 或 for 语句。这是因为块 只能包含 Statements,不能包含 SourceElements,其中 函数声明是。如果我们仔细查看生产规则,我们 可以看到直接在 Block 内允许 Expression 的唯一方法 是当它是 ExpressionStatement 的一部分时。然而, ExpressionStatement 被明确定义为不以“function”开头 关键字,这正是 FunctionDeclaration 不能出现的原因 直接在语句或块中(注意块只是一个列表 声明)。

由于这些限制,只要函数直接出现在 块(例如在前面的示例中)它实际上应该是 认为是语法错误,而不是函数声明或表达式。这 问题是我见过的几乎没有一个实现可以解析 这些功能严格按照规则(例外是 BESEN 和 DMD 脚本)。他们以专有的方式解释它们。

【讨论】:

  • Block 真的指的是if ( ) 部分还是它后面的{ body } 部分?
  • 我几乎可以肯定 if ( ) 本身也被认为是一个块......但不是 100% :(
  • 因为您可以在 for ( ) 中声明一个变量,并且它仅在其块内有效...我想它的工作方式相同
  • 如果你看引用之前的代码,它看起来像我写的。他说的是if (foo) { function bar() {...} }
  • 是的,OP的代码中的函数不在block中,它被定义为{ StatementList }
【解决方案3】:

函数声明是statementsif-statement 的条件部分是一个表达式,所以你拥有的是一个函数表达式;它不能是函数声明。所以它没有被提升,因为只有函数 声明 是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-16
    • 2020-08-09
    • 2021-09-13
    • 2020-12-03
    • 2014-01-01
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    相关资源
    最近更新 更多