2013-02-27 85 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';這樣,任何看到你的代碼的人都知道你有意將它變成一個全局變量。