【问题标题】:JavaScript scope in a try blocktry 块中的 JavaScript 范围
【发布时间】:2012-05-13 13:52:45
【问题描述】:

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

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

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

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

【问题讨论】:

  • 在我看来这只是一个关于变量范围的问题,而不是 try 块中的变量范围。

标签: javascript scope


【解决方案1】:

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

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

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

let xyz = "Outside";

try {
    let xyz = "Inside";

    throw new Error("Blah");
} catch (err) {
    console.log(xyz);
}

【讨论】:

  • 多么令人兴奋和大开眼界的例子!
【解决方案2】:

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

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

如果something 为假,您的示例会将undefined 传递给magicFunction,因为magicVar 尚未分配给任何东西。

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

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

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

(function() {
  x = 2;
  var x;
  alert(x);
})();
alert(x);

【讨论】:

  • 你给出的例子不是很好,因为它是undefined,因为window.aundefined
  • @gdoron 我不确定我明白你在说什么。如果你只是尝试单独运行alert(a),它会抛出类似a is 'undefined'的错误。
  • 问题是a 可以是未定义的,因为它在outerscope中未定义。看看这个demo 如果你删除var x 你仍然会得到相同的结果。
  • @gdoron 我还是不明白你在说什么。我的观点是this code 将运行没有错误,而this code 将抛出一个错误。
  • Alert two 然后抛出错误? (如果 x 没有在外层范围内定义)
【解决方案3】:
  • 在 javascript 中,只有函数会创建一个新的上下文 -closure。
  • 变量的每个定义实际上都是在其作用域顶部的变量声明和在定义所在位置的赋值。

变量

  • 函数范围
  • 提升至最高功能
  • 在同一范围内重声明同名是无操作的

您可能想阅读MDN scope cheat sheet

由于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();​

Demo

所以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 吗?

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

【讨论】:

  • 我被撕裂了!我喜欢你和彼得奥尔森的。投赞成票:)
  • @DarrenGreen。 :) 不要难过。只需选择您认为得到的最佳答案即可。 (我不喜欢 Stackoverflow 的想法,即接受的答案会弹出到顶部 {我听到 hoisting 了吗?:)},可能对问题决定哪个答案是最好的。)如果是彼得的答案,我很满意,我不会与没有答案的人竞争。
  • 您的备忘单链接被视为过时的内容。喜欢那个页面上的大警告栏——你不会错过的!哈哈
【解决方案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 在函数中随处可用,但在你给它一个值之前它是未定义的。

您的变量具有函数作用域。

【讨论】:

    【解决方案5】:

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

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

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

    【讨论】:

      【解决方案6】:

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

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

      • 功能先吊装。 示例:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-05
        • 1970-01-01
        • 1970-01-01
        • 2011-07-25
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多