JavaScript入门教程

JavaScript简介
JavaScript语法基础
JavaScript流程控制
JavaScript函数
面向对象编程
JavaScript事件
JavaScript DOM
正则表达式
JavaScript BOM
AJAX

专题分析

浏览器兼容性
JS优化
Web前端开发规范
编辑器推荐
总结和笔记

学习助手

对象参考手册
ECMAScript分析
数据中心
QQ交流群

JS全局变量的副作用

JavaScript通过函数管理作用域。局部变量是在函数内部使用 var 声明的变量;全局变量则会在下列情况下出现:
  1. 在任何地方不使用 var 声明变量,或者直接向未声明的变量赋值。
  2. 在函数外部使用 var 声明的变量。
  3. 以 window. variable 形式声明的变量。

全局变量的问题在于,你的JavaScript应用程序和web页面上的所有代码都共享了这些全局变量,他们住在同一个全局命名空间,所以当程序的两个不同部分定义同名但不同作用的全局变量的时候,命名冲突在所难免。

web页面包含不是该页面开发者所写的代码也是比较常见的,例如:
  • 第三方的JavaScript库
  • 广告方的脚本代码
  • 第三方用户跟踪和分析脚本代码
  • 不同类型的小组件,标志和按钮

比方说,该第三方脚本定义了一个全局变量,叫做result;接着,在你的函数中也定义一个名为result的全局变量。其结果就是后面的变量覆盖前面的,第三方脚本就一下子嗝屁啦!

因此,要想和其他脚本成为好邻居的话,应该尽可能少的使用全局变量,并且始终使用var来声明变量。

以下是几种常见的误将局部变量声明为全局变量的例子。

一、函数内部不使用 var 声明变量
function sum(x, y) {
   // 不推荐写法: 隐式全局变量
   result = x + y;
   return result;
}

此段代码中的result没有声明。代码照样运作正常,但在调用函数后你最后的结果就多一个全局命名空间,这可以是一个问题的根源。

经验法则是始终使用var声明变量,正如改进版的sum()函数所演示的:

function sum(x, y) {
   var result = x + y;
   return result;
}

二、使用任务链进行部分 var 声明

// 反例,勿使用
function foo() {
   var a = b = 0;
   // ...
}

上面的片段中,a是本地变量但是b确实全局变量,这可能不是你希望发生的。

此现象发生的原因在于这个从右到左的赋值,首先,是赋值表达式b = 0,此情况下b是未声明的。这个表达式的返回值是0,然后这个0就分配给了通过var定义的这个局部变量a。换句话说,就好比你输入了:
    var a = (b = 0);
如果你已经准备好声明变量,使用链分配是比较好的做法,不会产生任何意料之外的全局变量,如:
function foo() {
   var a, b;
   // ... a = b = 0; // 两个均局部变量
}

IT学苑提示隐式全局变量和明确定义的全局变量间有些小的差异,就是通过delete操作符让变量未定义的能力:
  • 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。
  • 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。
这表明,在技术上,隐式全局变量并不是真正的全局变量,但它们是全局对象的属性。属性是可以通过delete操作符删除的,而变量是不能的。

使用即时函数函数,避免变量污染

为了避免全局的变量的污染,IT学苑推荐一种即时函数的写法,即将具有独立功能的代码放在一个即时函数里面。如下:
(function(){
    //输出变量 itxueyuan
    var itxueyuan="http://www.itxueyuan.com/javascript/";
    document.write(itxueyuan+"<br />");
})();

document.write(itxueyuan);

结果,第一次输出http://www.itxueyuan.com/javascript/,第二次提示语法错误:


可见,变量itxueyuan的作用域仅限于及即时函数内部,有效避免了变量的污染,尤其是在引入第三方代码的情况下。由于IT学苑的JS代码很大一部分使用了这种模式,有效避免了变量冲突。