2010-04-24 127 views
2

我剛剛開始學習JavaScript,並試圖編寫一個腳本,它可以在頁面上創建div網格。我的腳本中的全局變量和局部變量

這裏的腳本:

var tileWidth=50; 
var tileHeight=100; 
var leftPos=10; 
var topPos=10; 
var columns=10; 
var rows=10; 
var spacing=5; 

$('document').ready(function() { 
placeTiles(); 
}); 

function makeRow() { 
for (var i=0; i<columns; i++) { 
    $('#canvas').append('<div class="tile" style="left:' + leftPos + 'px;top:' + topPos + 'px;"></div>'); 
    var leftPos = leftPos + tileWidth + spacing; 
} 
} 

function placeTiles() { 
for (var i=0; i<rows; i++) { 
    makeRow(); 
    var topPos = topPos + tileHeight + spacing; 
} 
} 

目前,100個<div>小號生成,所有10px的的頂部位置和不確定(排在第一<div>)左側位置或NaN。

我應該做什麼不同?爲什麼不能makerow()看到我的全球leftPos變量(以及所有其他變量)?

謝謝。

+0

不使用VAR在leftPos面前,因爲你已經宣佈離開後,在你的腳本的頂部 – 2010-04-24 22:55:03

+0

leftPos對不起,在你的foreach中從var var leftPos中刪除var – 2010-04-24 22:55:31

回答

3

「爲什麼Makerow()看不到我的全局leftPos變量(以及所有其他變量)?」

因爲var不是聲明。它是一個函數(範圍)範圍的註釋。在頂級範圍var本質上不做任何事情(全局執行上下文/範圍窗口對象),因此它與window.leftPos = 10或只是leftPos = 10相同。在makeRow你基本上有:

function makeRow() { 
var leftPos = undefined // this is "hoisted" to the TOP of the function 
for (...) { 
    // ... 
    leftPos = leftPos + tileWidth + spacing 
} 
} 

東西看起來可疑嗎? :-)

對此的兩種解決方案是1)使用不同的變量名(推薦)2)使用窗口對象的'global'leftPos屬性(如下所示)。而且,即使它只是一個範圍範圍的註釋,如果你把var放在頂端(無論如何,請參閱上文),它通常會導致更清晰的代碼。例如:

function makeRow() { 
var leftPos = window.leftPos // or use a different name, which is what I'd do 
for (var i=0; i<columns; i++) { 
    $('#canvas').append('<div class="tile" style="left:' + leftPos + 'px;top:' + topPos + 'px;"></div>') 
    leftPos = leftPos + tileWidth + spacing 
} 
} 

欲瞭解更多信息,請參見: Identifier Resolution, Execution Contexts and Scope Chains

+1

哦,我想我明白了!當我做'var leftPos = leftPos + tileWidth + spacing'時,我聲明瞭一個局部變量leftPos,它覆蓋了具有相同名稱的全局變量(實際上我想要的),但是當我嘗試將全局變量賦值給它已經被覆蓋了!所以我可以使用window.leftPos的替代方法引用全局變量,或者給全局變量賦予不同的名稱。謝謝! – Acorn 2010-04-24 23:11:24

+1

@Acorn:覆蓋可能不是正確的術語。全局變量仍然存在,但由於您有另一個同名的局部變量,全局變量將不可訪問,除非您使用'window.leftPost'。 – 2010-04-24 23:21:41

+2

帶陰影的是我相信的術語。 – wombleton 2010-04-24 23:34:13

1

你聲明leftPos的功能範圍爲var leftPos,隱藏全局聲明。如果你沒有聲明不使用var

+0

但是我已經把'leftPos'聲明爲gloval var a t腳本的開始。我認爲我可以在該函數中分配一個具有相同名稱的局部變量,以便它將採用全局變量,向其中添加其他變量,然後覆蓋它,以便函數中的所有其他循環將使用局部變量而不是全局變量。然後下一次該函數被調用時,它會重置回全局變量。所以我不能那樣做? – Acorn 2010-04-24 22:57:05

1

在JavaScript中,你可以有你的變量函數範圍或全局範圍。

如果在不同作用域中有兩個相同名稱的變量,則首先給出在函數作用域中聲明的變量。

因此,你必須在腳本的頂部全球範圍內聲明的leftPostopPos變量,你也有他們makeRow()placeTiles()函數內聲明。關鍵字var用於變量聲明,不用於變量賦值。

您只需從函數中刪除var的變量聲明,以便使用全局變量。簡單地使用:

leftPos = leftPos + tileWidth + spacing; 

// and 

topPos = topPos + tileHeight + spacing; 

但是,您應該考慮完全避免全局變量。全球化是邪惡的。

延伸閱讀: