37

假设我正在尝试执行这个 JavaScript 片段。假设未声明的变量和方法在上面的其他地方声明,something并且somethingElse评估为 boolean-true。

try {
    if(something) {
        var magicVar = -1;
    }

    if(somethingElse) {
        magicFunction(magicVar);
    }
} catch(e) {
    doSomethingWithError(e);
}

我的问题是:范围是什么,可以像我所做的那样magicVar传递它吗?magicFunction

4

6 回答 6

73

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

let如果在块内定义了变量try,它将不在catch(or finally) 块内的范围内。它需要在封闭块中定义。

例如,在以下代码块中,控制台输出将为“Outside”:

let xyz = "Outside";

try {
    let xyz = "Inside";

    throw new Error("Blah");
} catch (err) {
    console.log(xyz);
}
于 2016-09-30T19:07:20.717 回答
28

Javascript具有函数范围。这意味着magicvar它将从它声明的函数的开头一直存在到该函数的结尾,即使该语句从未执行过。这称为变量提升。函数声明也会发生同样的事情,这又称为函数提升

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

您的示例将传递undefinedmagicFunctionifsomething为 false,因为magicVar尚未分配给任何东西。

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

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

POP QUIZ:以下代码有什么作用?

(function() {
  x = 2;
  var x;
  alert(x);
})();
alert(x);
于 2012-05-04T02:03:57.027 回答
6
  • 在 javascript 中,只有函数会创建一个新的 context -closure。
  • 变量的每个定义实际上都是在其作用域顶部的变量声明和在定义所在位置的赋值。

变量

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

您可能想阅读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 吗?

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

于 2012-05-04T02:03:41.533 回答
4

由于javascript“提升”(google it),您的变量声明代码被翻译为:

function yourFunction() {
  var magicVar;
  try {
      if(something) {
          magicVar = -1;
      }

      if(somethingElse) {
          magicFunction(magicVar);
      }
  } catch(e) {
      doSomethingWithError(e);
  }

} //end of your function

“提升”将所有变量声明移动到函数的顶部。所以magicVar在函数中的任何地方都可用,但在你给它一个值之前它是未定义的。

您的变量具有函数范围。

于 2012-05-04T02:05:42.280 回答
1

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

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

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

于 2012-05-04T02:02:30.757 回答
1

我同意变量提升和函数提升,我想强调两个重点。

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

  • 功能先吊装。例子 :

        b(); // output : 3
        var b = 2;
        function b(){
         return 3;
        }
    
于 2018-05-10T12:30:12.753 回答