2012-02-02 98 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,但为什么会发生?