3

我试图理解 Javascript 中的词法作用域。在下面的示例中,我在另一个函数中编写了一个函数。当我运行它时,我希望在第一个警报中弹出“爸爸”,在第二个警报中弹出“妈妈”。但实际发生的是,它在第​​一个弹出窗口中显示“未定义”,在第二个弹出窗口中显示“妈妈”。

function first(){
  var x = "dad"; 
  function second(){
    alert(x);
    var x = "mom";
    alert(x);
  }
  second();
}
first();

有人可以解释为什么在父函数中定义的变量“x”在子函数中不可见吗?奇怪的是,当我删除子函数中变量“x”的声明时,它工作正常。有人可以深入了解这里有效的词汇范围场景吗?

4

2 回答 2

5

in 'second' 声明了var x一个变量 'x',它在外部函数中隐藏了变量 'x'。在“第二个”函数中对“x”的任何引用都是指该变量,即使它在声明之前也是如此。声明之前的变量值将是“未定义”。

您可以查找“吊装”以获取更多信息。请参阅:http: //www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

于 2014-03-16T13:12:14.140 回答
4

您通过x在. _ 这使得它与在 中声明的不同。secondvaralertxfirst

此外,JavaScript 使用一种称为提升的技术。在作用域中声明变量时,该声明会在执行前传递期间移动到作用域的顶部。如果声明和赋值在一个语句中完成,则声明从赋值中分离出来。声明被移动到范围的顶部,导致一个未定义的变量,而赋值则留在原来的位置。

pre-pass 后的结果代码如下所示(我只在这里展示了变量的提升,只留下了函数)

function first(){
    var x;
    x = "dad";
    function second(){
        var x; //new variable in local scope, declared not defined
        alert(x); //alerts undefined
        x = "mom"; //defines local `x` as "mom"
        alert(x); //alerts "mom"
    }
    second();
}
first();

因此,第一个alertx是新的和未定义的,第二个它是定义的。同时,xin的值first保持不变。

为了得到您所期望的,并x在两个函数中保持相同,您将从中删除var声明second并离开分配:

function first(){
    var x = "dad"; 
    function second(){
        alert(x);
        x = "mom";
        alert(x);
    }
    second();
}
first();
于 2014-03-16T13:16:28.993 回答