2013-02-27 34 views
0

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

如果在声明变量之前写入变量var将变量赋值给本地作用域,那么当初始化变量以将其保留在本地作用域中时,是否需要稍后编写var?例如:

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

自从我宣布someVariable在局部范围内与var,但随后没有使用var初始化someVariable,并JavaScript的认为我只是初始化一个变量在局部范围内,或者说我声明一个变量局部范围,然后宣布在全局范围内初始化另一个变量?

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

+0

我还要补充一点,我目前正在努力提高我对谈论JavaScript时使用的正确术语的理解。因此,我不会因为如何使用术语而被纠正而感到不安。 – 2013-02-27 20:57:15

回答

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前面var,它将本地范围应用于该变量。一旦函数完成,变量的原始范围被恢复(或者重新范围丢失,如果你想这样看)。感谢@zzzzBov指出这一点。

希望这会有所帮助。

+0

“这样做定义了一个具有相同名称的新变量”并不完全。 'var'只将变量设置为该范围,重复使用'var'不会影响变量是否被替换。 *赋值*是否影响变量值是否发生变化。为了说明这个'var x = 1; var x;'仍然有'1'的值,而不是'undefined'。 – zzzzBov 2013-02-27 20:53:23

+0

@zzzzBov优秀的观察,谢谢。我会更新我的答案。 – Madbreaks 2013-02-27 20:54:34

3
var something = "Initial value." 

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

something = "New value." 

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

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

+0

这很有趣。所以这意味着如果一个人不断地在全局范围内分配变量(在我开始理解范围之前,我不习惯这样做),那么引擎有可能找到一个错误的变量来赋值给? – 2013-02-27 20:54:21

+1

是的,在某些情况下完全有可能通过在您的作用域本地定义相同的名称并在其中包含该函数来意外“捕获”某个函数试图引用的全局。 – 2013-02-27 20:56:02

2

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

不完全是。

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

自从我宣布someVariable在局部范围内使用var,但随后没有使用VAR初始化someVariable,并JavaScript的认为我只是初始化一个变量在局部范围内,或者说我在声明一个变量局部范围,然后在全局范围内声明并初始化另一个变量?

该例中只有一个someVariable

后来,当我想再次改变someVariable的价值,我需要的变量表达式

var之前写的变种无论身在何处作用域为整个函数,变量在它出现的功能。

0

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

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

如果你没有使用var关键字每次你改变变量的时候,你不会得到不同的变量。最新的声明只会覆盖最旧的声明。所以除了初始化之外,使用var关键字没有意义。要更改someVariable的值,可以像上例中那样对变量名称进行赋值。

基本上,如果存在具有相同名称的范围没有使用可变var将创建一个新的变量。

现在利用这个代码,例如:

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';这样,任何看到你的代码的人都知道你有意将它变成一个全局变量。