为什么 'error' 变量重新分配的功能范围不在 catch{} 块内?

Why isn't 'error' variable reassignment functionally scoped inside of catch{} block?

我正在 JavaScript 中使用 try-catch 块,并且 运行 有一些我不完全理解的变量作用域行为。

我知道 console.log(boo)20 打印到控制台,因为该变量已使用 var 关键字声明,因此它在功能范围内(即不是块范围到 catch块)。

但是,我不明白为什么 err 变量没有像 boo 变量一样限定在 IIFE 中。因此我不明白为什么它在 catch 块之外 undefined

(function() {
  try {
    throw new Error();
  } catch (err) {
    var err = 10;
    var boo = 20;
    console.log(err); //'10' (as I expect)
  }
  // Why doesn’t this log '10' ???
  console.log(err); // 'undefined' (but I expected '10')

  console.log(boo); // '20' (as I expect)
})();

我找到了答案。

是因为异常'identifier'(即上例中的'err'变量)在catch块执行完毕后不可用。这似乎是在 JS 中处理作用域的一种特殊情况,在进行一些挖掘之前绝对是 'gotcha'。

希望这对其他人有帮助!

来自docs

虽然 var 将符号提升到功能块的顶部,但 catch 子句的 "argument" 是该子句的局部。由于您已将提升值命名为与子句符号相同的名称,因此这可能会造成混淆。本质上,您的代码与:

(function () {
var err;
var boo;
try {
    throw new Error();
  } catch (err) {
    err = 10; // Set the catch's "local" `err` identifier to `10`
    boo = 20; // Set the hoisted `boo` identifier to `20`
    console.log(err);
  }
  console.log(err); // The hoisted `err` was never set.
  console.log(boo); // ’20’ (as I expect)
})();

您可能还会将 catch 子句中的 err 视为 function/clause 的参数;它的作用域是函数的局部作用域,与全局作用域无关(无论该符号是否存在于全局作用域中)。