全球变量应该避免吗?

时间:2012-02-02 16:03:04

标签: javascript

学习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中不存在访问修饰符,应避免使用全局变量吗?

8 个答案:

答案 0 :(得分:2)

不惜一切代价避免全局变量的简单原因是,您永远无法确定哪些其他脚本同时被加载。因此,为了避免可能在真正丑陋的错误场景中出现的冲突,您至少应该将自己的代码包装到一个closured函数上下文中。

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

这种简单的模式完全避免了任何冲突。

答案 1 :(得分:2)

为了使您的行为符合预期,您需要创建实例属性,而不是使用全局变量widthheight。您当前的方法将导致使用相同变量的多个Rectangle实例。

尝试:

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

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

等...

正如其他人所指出的那样,全局变量widthheight将由当前作用域中的所有其他代码共享(注意:JavaScript只有函数级作用域,而不是块级)。

答案 2 :(得分: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,否则您将修改全局宽度和高度变量,并且这些值不会绑定到Rectangle的单个实例。
  2. 最好使用函数表达式而不是构造函数的函数声明:var Rectangle = function(w, h) { ... }而不是function Rectangle() { ... }
  3. 您还可以将所有代码包装在一个立即执行的函数中,以便完全避免全局命名空间污染(请参阅jAndy回答)
  4. 对象的初始宽度和高度可以在构造函数中传递以进行初始化(否则宽度和高度设置为0 - 或其他任何值 - 默认情况下)。
  5. 这些规则肯定是写的(参见 Javascript:D.Crockford的好部分)。

答案 3 :(得分: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中不存在访问修饰符,应避免使用全局变量吗?

没有。无论编程语言如何,都应该避免全局始终

答案 4 :(得分:0)

应该避免全球化。你应该将东西包装在封闭中。

只有在想要公开功能时才使用全局变量。

答案 5 :(得分:0)

是的,它仍然是真的。你应该始终避免使用全局变量。

在您的示例width中,height是全局的。如果这是完整的代码,那就不是问题了。但是,如果你后来决定引入另一个名为GameField的“类”,那该怎么办?它自然也有宽度和高度。我在这里闻到了麻烦。

答案 6 :(得分:0)

通常在OOP Javascript中,您可以使用类定义创建一个闭包,以避免污染全局范围。

var Rectangle;

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

  Rectangle = function (){}
  ...

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

通过这种方式,您可以定义私有属性并且仍然具有干净的全局空间:)

另外,为了防止注释中描述的问题MДΓΓБДLL仍然保留私有属性和getter / setter,这是要走的路

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 vars的完整性,否则使用其他答案中所述的公共属性要容易得多。

答案 7 :(得分: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将返回100.嗯,你说,这不是那么糟糕。我还是可以读这个。

但是让我们修改最后两行:

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,但为什么会这样呢?