在 if 语句中声明函数或不声明函数的原因

Reasons to or not to declare functions in an if-statement

提问人:Ooie 提问时间:2/29/2020 最后编辑:Ooie 更新时间:3/1/2020 访问量:1050

问:

我需要一些关于屏幕后面发生的事情的确认。

MDN 中有一篇文章说,我们不应该在块级中声明函数,例如在 if 语句中。因为它在整个浏览器中都是不一致的,并且与ES2015之前(或ES6之前)有关。

除非条件为 true,否则不会创建 if 语句中的函数。

我想知道,如果条件为真,假设 JavaScript 加载并同步设置后 5 分钟后,它会创建函数吗?它是否仍然具有代码的内存以创建函数,或者它是否被转储到未使用的代码中?

我想知道即使在 if 语句完成后,该函数是否仍然存在。它是可访问的吗?它可以访问多长时间?在 if 条件为 false 之前是否可以访问它?结果与 ES6 和 ES6 之前的结果有什么不同吗?我听说 if 语句中没有 ES6 之前的范围。

例如:

if (condition) { function foo() {console.log(“hello world”); } }

在MDN中阅读了一篇关于“非严格代码中的块级函数”下的“函数”的文章后,我感到很困惑:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

javascript if 语句

评论

1赞 QuentinUK 2/29/2020
请参阅 stackoverflow.com/questions/60416842/...,例如不一致。
4赞 RobG 2/29/2020
Javascript 是单线程的,代码在执行时进行评估,而不是在执行之前或之后。只是不要在里面声明函数,如果块作为行为不一致。如果必须有条件地创建函数,请使用函数表达式。
0赞 user2864740 3/1/2020
stackoverflow.com/a/31461615 - 似乎回答了相关的主要问题。不知道为什么我必须通读一篇文章才能得到它。

答:

0赞 CertainPerformance 2/29/2020 #1

如果条件为真,假设 JavaScript 加载并同步设置后 5 分钟后,它会创建函数吗?

该函数将在运行后立即创建。if

它是否仍然具有代码的内存以创建函数,或者它是否被转储到未使用的代码中?

我想知道即使在 if 语句完成后,该函数是否仍然存在。它是可访问的吗?它可以访问多长时间?

无论函数是否在块中声明,此行为都是相同的:如果将来没有任何东西可以引用该函数(例如,如果块结束并且块内没有任何内容引用该函数),它最终将被垃圾回收。在 GC 运行之前,该函数可能仍“存在”在内存中一段时间。if

例如,应该清楚的是,以下函数应始终继续存在,至少在重新加载页面之前是这样:

// IIFE, to get off the top level
(() => {
  if (true) {
    function foo() {
      console.log('clicked');
    }
    window.addEventListener('click', foo);
  }
})();

这是因为已传递了对函数的引用。addEventListener

但是以下函数将获得 GC'd(可能在页面加载后一秒钟或几秒钟 - 它取决于底层引擎,并且对 Javascript 不可见):foo

// IIFE, to get off the top level
(() => {
  if (true) {
    function foo() {
      console.log('clicked');
    }
  }
})();

如果在作用域变量的块完成之前没有保存对函数的引用,则该函数将无法在任何地方访问,并且将被 GCd。

问题的其余部分看起来与“在哪里可以引用函数”基本相同,这在 Bergi 的回答中得到了最好的描述。这有点复杂,并且行为会有所不同,具体取决于您使用的是严格模式、环境的 ES 版本还是环境本身(实现并不总是符合规范)。

对于可预测的、易于阅读的代码,最好永远不要在非功能块中使用函数声明;仅当直接在功能块内部使用函数声明时。

(请注意,函数表达式,其中函数被用作值并传递给某物或立即调用或显式分配给变量,与函数声明不同 - 函数表达式很好,只是函数声明的奇怪行为有问题。另请注意,根据注释,“函数声明”有时称为“函数语句”。

评论

1赞 user2864740 3/1/2020
出现在 if 块中的函数语句是问题所在。函数表达式正常。所以其他的东西很好,但这并不重要,因为基本概念是跨实现的不明确/不一致的行为。
0赞 user2864740 3/1/2020
如果这与ES3/5/6等不同,则应按照OP的要求具体解决。
1赞 CertainPerformance 3/1/2020
我已经说过永远不要在非功能块中使用函数声明;只有在直接在功能块中使用函数声明时才使用函数声明。当然,函数表达式是完全不同的,因为它们是表达式,而不是奇怪的、有时被吊起的东西
0赞 CertainPerformance 3/1/2020
如果你对措辞感到困惑,我所说的“函数声明”听起来与你所说的“函数语句”是一样的——它们都是与任何其他表达式无关的结构function fnName() { ...