0

我正在研究 Javascript 中的变量作用域,并且遇到了变量声明和变量初始化之间的区别。通过与我认识的开发人员交谈,我的理解是,var在变量声明之前编写会将变量分配给本地范围,而var在声明变量之前不编写会将变量分配给全局范围。这是真的?

如果在声明变量之前写 var 确实将变量分配给本地范围,那么是否需要var稍后在初始化变量时将其保持在本地范围内?例如:

var someVariable;
// Do some things with JavaScript
someVariable = 'Some Value'

既然我someVariable在局部作用域中用声明了var,然后又someVariable在没有使用的情况下进行了初始化var,那么 JavaScript 是否认为我只是在局部作用域中初始化了一个变量,或者我在局部作用域中声明了一个变量,然后在全局中声明初始化了另一个变量范围?

稍后,当我想再次更改的值someVariable时,是否需要在变量表达式之前编写 var,或者 JavaScript 会知道我正在更改已声明的局部变量的值?从技术上讲,JavaScript 如何知道我何时更改已声明的局部变量的值,以及何时声明和初始化全局变量?

4

4 回答 4

3
var something = "Initial value."

这意味着:“在本地范围内创建一个变量并给它一个初始值”。本地范围是指您在其中使用此语句的函数。

something = "New value."

这意味着:“在最近的范围内找到变量'某物',并为其分配一个新值”。如果您使用第二个语句而不使用第一个语句,该语句将something在逐渐更大的范围内查找任何定义(包含您的函数的函数,如果它存在,包含该函数的函数等,直到它到达全局范围)。如果它找到一些东西,它将分配给一个已经存在的变量。如果它什么也没找到,它将创建一个具有该名称的全局变量。

如果您var首先使用,您只需确保此搜索始终在本地范围内停止。

于 2013-02-27T20:45:53.373 回答
2

这些是相同的:

var x;
// ...
x = 1;

...和...

var x = 1;

两者都在本地范围内定义一个变量并为其赋值。如果您想稍后在同一范围内更改变量的值,您可以简单地按名称引用它:

x = 2;

但是,如果您在不同的范围内,除非变量首先在全局范围内声明,否则您将无法访问它(它“超出范围”)。尝试这样做将在全局范围内定义一个具有该名称的变量。

function a(){
    var x = 1;
}

function b(){
    x = 2;  // 'x' in a is out of scope, doing this declares a new 'x' in global scope
}

a();
b();

在声明它的同一范围内引用变量时,您不需要在它前面加上前缀var,尽管您可以:

var x = 1;
// ...
var x = 2;

...没有必要这样做。虽然它将 2 分配给“x”,但它在逻辑上没有任何效果,因为 var 已经在本地范围内。但是,如果x已在全球范围内声明:

var x = 1;

function a(){
    var x = 2;
    console.log(x);
}

a();
console.log(x);

这将首先打印“2”,然后打印“1”。通过在函数中引用x前面的 with var,它将局部范围应用于变量。一旦函数完成,变量的原始范围就会恢复(或者重新范围丢失,如果你想这样看的话)。感谢@zzzzBov 指出这一点。

希望这可以帮助。

于 2013-02-27T20:42:53.790 回答
2

我的理解是,在变量声明之前写 var 会将变量分配给本地范围,而在声明变量之前不写 var 会将变量分配给全局范围。这是真的?

不是完全。

function foo() {
    var a = 1;
    function bar() {
        a = 2; // Still in the scope of foo, not a global
    }
}

既然我在本地范围内用var声明了someVariable,然后又在不使用var的情况下初始化了someVariable,那么JavaScript是否认为我只是在本地范围内初始化了一个变量,或者我在本地范围内声明了一个变量,然后又声明并初始化了另一个全局范围内的变量?

该示例中只有一个someVariable

以后想再修改someVariable的值时,是不是需要在变量表达式前写var

var作用域为整个函数的变量,无论它出现在函数中的什么位置。

于 2013-02-27T20:46:05.530 回答
0

如果使用 定义变量,则可以不反复var使用关键字来引用同一个变量。var这些引用相同的变量:

var someVariable;
//...code...
someVariable = 'rawr';

如果var每次更改变量时都使用关键字,则不会获得单独的变量。最新的声明只会覆盖最旧的声明。所以var除了初始化之外,使用关键字没有任何意义。要更改 的值someVariable,您可以像上面的示例一样对变量名进行赋值。

基本上,var如果该范围内没有同名的变量, using 将创建一个新变量。

现在以这段代码为例:

var someVariable = 'initialized';

function test1(){
  //this someVariable will be a new variable since we have the var keyword and its in a different scope
  var someVariable = 'test1';
  console.log(someVariable);
}

function test2(){
  //because there is no var keyword this refers to the someVariable in the parent scope
  someVariable = 'test2';
  console.log(someVariable);
}

console.log(someVariable); //initialized

test1(); //test1
console.log(someVariable); //initialized

test2(); //test2
console.log(someVariable); //test2

通过此示例,您可以看到根据您希望代码执行的操作,您可能会遇到问题。如果您想表现test2得像test1而忘记使用var关键字,那么当您期望是时,您会感到困惑someVariableinitialized而实际上却是test2

但是您也可以故意不使用var关键字,因为您想test2更新父变量。因此,var正确使用关键字很重要。

var初始化变量时不使用将在全局范围内创建变量。这不是好的做法。如果您想要全局范围内的变量,请手动将它们放在那里。即window.someVariable = 'initialize';这样任何其他看到您的代码的人都知道您故意将其设为全局变量。

于 2013-02-27T21:16:47.553 回答