尝试块中的 JavaScript 范围

JavaScript scope in a try block

本文关键字:JavaScript 范围      更新时间:2023-09-26

假设我正在尝试执行这个JavaScript代码片段。假设未声明的变量和方法是在上面的其他地方声明的,并且somethingsomethingElse计算结果为布尔值。

try {
    if(something) {
        var magicVar = -1;
    }
    if(somethingElse) {
        magicFunction(magicVar);
    }
} catch(e) {
    doSomethingWithError(e);
}

我的问题是:magicVar的范围是什么,是否可以像我一样将其传递给magicFunction

关于 Javascript 如何使用 var 处理这个问题还有很多其他很好的答案,但我想我会解决let的情况......

如果变量在try块内使用 let 定义,则它不会在catch(或finally)块内的范围内。 它需要在封闭块中定义。

例如,在以下代码块中,控制台输出将为"外部":

let xyz = "Outside";
try {
    let xyz = "Inside";
    throw new Error("Blah");
} catch (err) {
    console.log(xyz);
}

Javascript 具有函数作用域。这意味着magicvar从声明的函数的开头一直存在到该函数的末尾,即使该语句从未执行过。这称为可变吊装。函数声明也会发生同样的事情,这反过来称为函数提升

如果变量是在全局范围内声明的,它将对所有内容可见。这就是为什么全局变量在Javascript中被认为是邪恶的部分原因。

如果 something false,您的示例将undefined传递到magicFunction,因为magicVar尚未分配给任何内容。

虽然这在技术上是有效的Javascript,但它通常被认为是糟糕的风格,并且不会像jsLint那样通过样式检查器。像这样极其不直观的Javascript将毫无错误地执行

alert(a); //alerts "undefined"
var a;

弹出测验:以下代码有什么作用?

(function() {
  x = 2;
  var x;
  alert(x);
})();
alert(x);
  • 在javascript中,只有函数创建一个新的上下文闭包。
  • 变量
  • 的每个定义实际上都是变量在其范围的顶部的声明,以及定义所在位置的赋值。

变量

  • 函数作用域
  • 提升到其功能的顶端
  • 同一范围内同名的重新声明是无操作的

你可能想阅读MDN范围备忘单

由于hoisting你甚至可以做这样的事情:

function bar() {
    var x = "outer";
    function foo() {
        alert(x); // {undefined} Doesn't refer to the outerscope x
        // Due the the var hoising next:        
        x = 'inner';
        var x;
        alert(x); // inner
    }
    foo();
}
bar();​
bar();​

演示

因此,foo函数转换为如下所示的内容:

function foo() {
    var x;
    alert(x); // {undefined} Doesn't refer to the outerscope x
    // Due the the var hoising next:        
    x = 'inner';
    alert(x); // inner
}​

我的问题是:magicVar的范围是什么,是否可以像我一样将其传递给magicFunction?

定义好的...,是的,代码是有效的,但是如果变量声明在顶部,那么它的可读性较差,仅此而已。

由于javascript的"提升"(MDN描述),你的变量声明代码被翻译为:

function yourFunction() {
  var magicVar;
  try {
      if(something) {
          magicVar = -1;
      }
      if(somethingElse) {
          magicFunction(magicVar);
      }
  } catch(e) {
      doSomethingWithError(e);
  }
} //end of your function

"提升"将所有变量声明移动到函数的顶部。 因此,magicVar函数中的任何地方都可用,但在您为其指定值之前,它是未定义的。

变量具有函数作用域。

对于var,变量从函数的开头到函数的结尾都存在,无论它们在哪里声明,或者即使语句实际上曾经到达过。但是,它们将被undefined,直到为它们分配另一个值。

因此,在您的情况下,如果something是假的,但somethingelse是真的,您将调用magicFunction,其第一个参数是undefined

let关键字是在 Javascript 1.9 中创建的,并且仅在 Firefox 中可用(截至今天,2012 年 5月 3 日,据我所知),它声明了具有您可能习惯的作用域语义的变量。

我同意可变吊装和功能提升,我想强调两个要点。

  • 在 Catch 参数中定义的标识符是 err/e(error) ,范围为 Catch 定义的块。

  • 功能先吊。例:

        b(); // output : 3
        var b = 2;
        function b(){
         return 3;
        }