| 
                                             在JavaScript中“熟练”掌握并理解变量的作用范围非常必要,搞混变量作用域将会带来各式各样的奇葩问题,而且是难以查找的问题,尤其在复杂的代码环境中。对变量的作用范围心如明镜也能提高开发效率。什么时候我应该大肆书写变量名而不用考虑变量重复,什么时候应该谨慎处理,明白这些才能做到写代码犹如写文章,洋洋洒洒! 
 
 爆出一个我最近遇到的一个问题,就是关于局部变量后定义导致的undefined的问题,估计很少人会遇到这种情况,无意粗心就碰到了这个问题,特此我写了个简单的例子来阐述下(把它叫做“问题函数”吧): 
 
 function douwo(a,b){    console.log("第一层:a:"+a+",b:"+b);    var arg=arguments.length;    $("html").click(function(){       console.log("第二层:a:"+a+",b:"+b);       if(arg>2){          var b=8;       }    }); } douwo(1,2);//第一层:a:1,b:2 我把闭包函数的b=8误写成了var b=8;众所周知,函数的参数相当于该函数的局部变量。上面的代码可以写成: 
 
 function douwo(){    var a=1,b=2;    console.log("第一层:a:"+a+",b:"+b);    var arg=arguments.length;    $("html").click(function(){       console.log("第二层:a:"+a+",b:"+b);       if(arg>2){          var b=8;       }    }); } douwo();//第一层:a:1,b:2 这是很好理解的,关键不好理解的是当点击页面的时候,打印出来的是:第二层:a:1,b:undefined 可是一个函数中变量后定义有时候也会存在,科普下(针对新手),如: 
 
 function qlq(){    console.log(a);//undefined    var a=8; } 变量分声明和定义,当一个变量用var关键字的时候是声明,=赋值是定义,而在函数内变量后声明定义会把声明提前,而定义保留在原有的位置。所以上面的代码可以写成: 
 
 function qlq(){    var a;//声明,但未赋值    console.log(a);//undefined    a=8;//定义,赋值 } 而函数参数都会充当局部变量在内部提前声明,所以最上面的代码可以写成: 
 
 function douwo(a,b){    var a,b;    console.log("第一层:a:"+a+",b:"+b);    var arg=arguments.length;    $("html").click(function(){       console.log("第二层:a:"+a+",b:"+b);       if(arg>2){          var b=8;       }    }); } douwo(1,2);//第一层:a:1,b:2 外面那层很好理解,关键在于里面那个闭包函数: 
 
 $("html").click(function(){       console.log("第二层:a:"+a+",b:"+b);//第二层:a:1,b:undefined       if(arg>2){          var b=8;       }    }); 这又要来科普下计算机对变量的查找规则了:就近原则,所谓就近原则就是首先是从函数内部查找变量,如果没有找到就往外层找,注意,外层可能是父函数,或者全局(window),如果全局都找不到那就真的不存在这个变量了。 
 
 关键难以理解的是if(arg>2){var b=8;},理论上条件不成立就不会进到这if里面去,当然就不会执行var b=8;所以上一行的打印会出来外函数的a和b,但是事实不是这样的,虽然条件不成立不会执行,但是计算机还是阅读了这段代码,就像小学老师批改周记签上“已阅”,计算机阅过之后的代码是这样子的: 
 
 function douwo(a,b){    var a,b;    console.log("第一层:a:"+a+",b:"+b);//第一层:a:1,b:2    var arg=arguments.length;    $("html").click(function(){       var b;       console.log("第二层:a:"+a+",b:"+b);//第二层:a:1,b:undefined       if(arg>2){          b=8;       }    }); } douwo(1,2); 声明了但条件不成立所以没有定义,最终问题函数输出:第二层:a:1,b:undefined也就理解通了~, 这是个坑,巨大的坑! 
  
                                         |