【问题标题】:function declaration inside a block [duplicate]块内的函数声明[重复]
【发布时间】:2021-03-27 09:32:18
【问题描述】:

大家好,我遇到了这个问题

function test() {
  test2();
  if (true) {
    function test2() {
      console.log(a);
    }
    let a = 4;
  }
}

我检查了调试器以找出它的行为方式 我已经看到 test2 函数被提升了,但它被设置为 undefined

我的问题是为什么?当一个函数不在一个块内并且我在声明之前调用它时,由于创建阶段它会起作用,那么为什么在这种情况下它不起作用呢?

【问题讨论】:

  • 因为如果你在另一个可见区域声明它就不能使用函数
  • @СергейПетрашко - 比这更复杂。 :-) 在 OP 的代码中,他们可以使用 test2 after if 块,假设它们处于松散模式(上面没有 "use strict",但据我所知它是模块代码和已经严格)。
  • @T.J.Crowder ,我同意你的看法!我写那个是为了给方向)
  • 您正在调用一个尚不存在的函数。这就是js的工作方式。这完全是关于上下文和范围,逐行执行并填充范围。

标签: javascript


【解决方案1】:

块内的函数声明不同于作用域顶层的函数声明,因为......它们在一个块中。 :-) 它们只是最近(ES2015)并且部分标准化;在此之前,支持它们是规范的允许扩展,但不幸的是不同的 JavaScript 引擎对它们的支持略有不同(有时它们的支持会随着时间的推移而变化),所以标准化必须是在各种实现中表现基本相同的事物。

不过,您的示例是行为方式相同的示例之一,因此我们可以说出规范中的内容。在代码执行进入if 块之前,该函数不会分配给test2 标识符。这是你的代码:

function test() {
    test2();
    if (true) {
        function test2() {
          console.log(a);
        }
        let a = 4;
    }
}

test();

...这里是粗略在松散模式下的处理方式(在严格模式下有一个非常小的差异):

function test() {
    var test2; // Identifier declared and initialized with `undefined` here
    test2();
    if (true) {
        test2 = function test2() { // Function assigned here, at the top of the block
          console.log(a);
        };
        let a = 4;
    }
}

test();

如您所见,由于该函数尚未分配给 test2 变量,因此您无法在有调用的地方调用它。

从您的代码中不清楚,但对 test2 标识符的赋值被提升到函数声明出现的块的顶部。我们可以看到,如果我们不尝试过早调用它并将值记录在块之前的test2(它是undefined)和声明上方的块内(它是函数):

function test() {
    console.log(test2);         // undefined
    // test2();
    if (true) {
        console.log(test2);     // the function - assignment was hoisted
        function test2() {
          console.log(a);
        }
        let a = 4;
    }
    console.log(test2);         // still available here!
}

test();

严格模式的细微差别主要是标识符具有let 语义而不是var 语义,并且仅作用于块:

"use strict";
function test() {
    // Can't use `test2` here at all
    if (true) {
        console.log(test2);     // Now it exists and has been initialized with the function
        function test2() {
          console.log(a);
        }
        let a = 4;
    }
    // Can't use `test2` here at all
}

test();

我总是推荐使用严格模式,这也是原因之一。对我来说,在块内声明的函数只能在该块内访问是有道理的。

【讨论】:

  • (FWIW,我在我最近的书 JavaScript: The New Toys 的第 3 章中详细介绍了新的标准化函数声明。如果你'重新感兴趣。)
猜你喜欢
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
相关资源
最近更新 更多