2012-02-02 104 views
3

學習Javascript並有一個關於全局變量的問題。從我的閱讀中,最推薦不要使用它們。但是,在基於類的javascripting中,這個不成文的規則是否仍然適用?例如:應該避免全局變量?

var width = 0; 
var height = 0; 

<!-- constructor --> 
function Rectangle(){} 

<!-- getters/setters --> 
Rectangle.prototype.getWidth = function(){ 
    return width; 
} 

Rectangle.prototype.setWidth = function(w){ 
    width = w; 
} 

Rectangle.prototype.getHeight = function(){ 
    return height; 
} 

Rectangle.prototype.setHeight = function(h){ 
    height = h; 
} 

<!-- methods --> 
Rectangle.prototype.area = function(){ 
    return height * width; 
} 

var myRect = new Rectangle(); 
myRect.setWidth(5); 
myRect.setHeight(4); 
console.log(myRect.area()); //20 
console.log(myRect.getWidth()); //5 
myRect.setWidth(10); 
console.log(myRect.getWidth()); //10 
console.log(myRect.area()); //40 

我熟悉Java以及對類,屬性和方法使用訪問修飾符的能力。是否因爲Javascript中不存在訪問修飾符,應該避免使用全局變量?

回答

2

你可能會使用這個代碼,而不是

<!-- constructor --> 
var Rectangle = function(w, h) { 
    this.width = w || 0; 
    this.height = h || 0; 
} 

<!-- getters/setters --> 
Rectangle.prototype.getWidth = function() { return this.width; } 
Rectangle.prototype.setWidth = function(w) { this.width = w; } 
Rectangle.prototype.getHeight = function() { return this.height;  } 
Rectangle.prototype.setHeight = function(h) { this.height = h; } 

<!-- methods --> 
Rectangle.prototype.area = function(){ 
    return this.height * this.width; 
} 

var myRect = new Rectangle(5, 4); 
console.log(myRect.area()); //20 
console.log(myRect.getWidth()); //5 
myRect.setWidth(10); 
  1. 寬度和高度應該是this.widththis.height,否則你將改變全球的寬度和高度的變量和這些值將不會被綁定到單一矩形的實例。
  2. 最好使用函數表達式而不是構造函數的函數聲明:var Rectangle = function(w, h) { ... }而不是function Rectangle() { ... }
  3. 您也可以包裝所有代碼立即自我執行功能內,從而完全避免了全局命名空間污染(看jAndy答案)
  4. 初始寬度和你的對象的高度可以用於初始化的構造函數傳遞(否則寬度和高度默認設置爲0或其他任何值)。
  5. 這些規則肯定是寫的(參見參考文獻Javascript:D.Crockford的好作品)。
+0

這是正確的答案 – 2012-02-02 16:11:09

+0

this.width = w || 0; - 這是OR運算符的一個有趣用法。正確的是,如果沒有設置w,這將返回0? – worked 2012-02-02 18:50:35

+0

@worked that's correct – fcalderan 2012-02-02 19:50:55

0

全局應該避免。你應該封閉東西。

只有在需要公開功能時才使用全局變量。

1

這個不成文的規則還適用嗎?

是的,你應該總是避免全局性。我不知道爲什麼widthheight在您的代碼中被聲明爲Rectangle之外。你需要做大量使用的this

function Rectangle(h, w) { 
    this.height = h || 0; 
    this.width = w || 0; 
} 

<!-- getters/setters --> 
Rectangle.prototype.getWidth = function(){ 
    return this.width; 
} 

Rectangle.prototype.setWidth = function(w){ 
    this.width = w; 
} 

Rectangle.prototype.getHeight = function(){ 
    return this.height; 
} 

Rectangle.prototype.setHeight = function(h){ 
    this.height = h; 
} 

<!-- methods --> 
Rectangle.prototype.area = function(){ 
    return this.height * this.width; 
} 

是因爲在Javascript中不存在訪問修飾符應避免全局?

編號全局應該總是應該避免,不管編程語言如何。

+0

嘗試使用BASIC進行編程而不使用全局變量:-) – 2012-02-02 16:07:43

+1

讓我停下來試試「在BASIC中編程」。「我會通過 – 2012-02-02 16:11:37

2

不惜一切代價避免全局變量的一個簡單原因是,您永遠無法確定哪些其他腳本可以同時加載。所以爲了避免可能以真實醜陋的錯誤情況出現的衝突,您至少應該將自己的代碼包裝到一個closured函數上下文中。

(function() { 
    // all of your code here 
}()); 

這個簡單的模式完全避免了任何衝突。

+0

除非所有的'Rectangle'實例要具有相同的尺寸,否則這不是刪除全局變量的正確方法。 – 2012-02-02 16:10:07

0

是的,這仍然是事實。您應該始終避免使用全局變量。

在你的例子中widthheight是全球性的。如果這是完整的代碼,那不是什麼問題。但是如果你以後決定引入另一個叫「GameField」的「班級」呢?它自然也有寬度和高度。我在這裏聞到麻煩。

2

爲了得到這個表現你的期望,你將需要創建實例屬性,而不是使用全局變量widthheight。您當前的方法會導致使用相同變量的多個Rectangle實例。

嘗試:

function Rectangle() { 
    this.width = 0; 
    this.height = 0; 
} 

Rectangle.prototype.setWidth = function(w) { 
    this.width = w; 
}; 

等等

正如其他人所指出的,全局變量widthheight將在當前範圍內的所有其他代碼共享(NB的JavaScript只有函數。級別範圍,而不是塊級)。

0

通常在OOP中,您可以使用類定義創建閉包,以避免污染全局範圍。

var Rectangle; 

(function() { 
    var width = 0; 
    var height = 0; 

    Rectangle = function(){} 
    ... 

})(); // the() execute the function with the closure 

這種方式,你能夠定義私有屬性,仍然有一個乾淨的全球空間:)

另外,爲了防止MДΓΓБДLL在註釋中說明,同時仍保持私有屬性和getter問題/制定者,這是去

function Rectangle() { 
    // Private properties 
    var width = 0, 
     height = 0; 

    // Public methods using private properties 
    this.setWidth = function(value) { 
    width = value; 
    } 

    this.setHeight = function(value) { 
    height = value; 
    } 
} 

容易得多的方式是無論如何使用公共屬性,如對方回答說,除非你真的關心widthheight瓦爾的完整性。

+0

除非所有的'Rectangle'實例具有相同的尺寸,否則這不是' t正確的方法來刪除全局變量 – 2012-02-02 16:10:02

+0

您的權利!我會提供一個更好的示例 – Davide 2012-02-02 16:28:06

0

它更多的是一個通用的編碼標準。全局變量是邪惡的,要生硬。

所以,假設您有以下代碼。

var width = 10; 

<!-- constructor --> 
function Rectangle(){} 

<!-- getters/setters --> 
Rectangle.prototype.getWidth = function(){ 
    return width; 
} 

Rectangle.prototype.setWidth = function(w){ 
    width = w; 
} 

var myRect = new Rectangle(); 
console.log(myRect.getWidth()); 

那麼,這將做你想做的事情,輸出10到控制檯。

但是,現在,讓我們說,開發商是在一個稍晚,並增加了構建myRect和喜歡的console.log之間的新行:

width=width * 10; 

現在的console.log將返回呃,你說,這並不壞。我仍然可以閱讀這個。

但是,讓我們修改最後兩行是:

var myRect = new Rectangle(); 
doSomethingCool(); 
console.log(myRect.getWidth()); 

function doSomethingCool() { 
    LOTS o code; 
    width = "10px"; // I need this to update the style sheet. 
    LOTS o code; 
} 

突然變得更難弄清楚發生了什麼實際發生的情況。

當然console.log會輸出10px,但爲什麼會發生?