`

js变量作用域

 
阅读更多
JavaScript的函数是在局部作用域内运行的,在局部作用域内运行的函数体可以访问其外层的(可能是全局作用域)的变量和函数。JavaScript的作用域为词法作用域,所谓词法作用域是说,其作用域为在定义时(词法分析时)就确定下来的,而并非在执行时确定,如下例:
var str = "global";   
function scopeTest(){   
    alert(str);   
    var str = "local";   
    alert(str);   
} 

scopeTest();//先打印undefined,然后打印local(注意:而不是先打印global,再打印local)

提到“词法作用域”,就必须得同时提到“作用域链”,两者结合才能有效理解:
第1行的str(global)在定义时首先被存入作用域链的头部即全局作用域;
在调用scopeTest时,js解释器生成1个调用对象(call object),并将scopeTest内通过var定义的所有变量设为它的一个属性(此处只有一个用var定义的变量str),然后再把这个对象加到作用域链的最前端,通俗理解即具有最优先的访问权;
在访问str时,首先查询scopeTest的调用对象,如果从中没找到str则查询仅挨该对象的上一个作用域,以此类推直至全局作用域;
此例中从调用对象中即可查到str,因此全局对象中的str被覆盖:第3行中,调用对象中有str定义但未赋值,因此为undefined;第4行,赋值;第5行,有值,是local。
var str = "global";      
function scopeTest(){      
    alert(str);    //global     
}         
scopeTest();

为什么这里是global?因为scopeTest的调用对象里没有str的定义,因此必须查询全局作用域,所以得出global。
为什么“词法作用域”的效果是“函数在定义它的作用域中执行,而不是执行它的环境”?那是因为函数始终只能沿着定义它时就确定了的“作用域链”逐级访问变量,与外界执行环境无关。

一些编程习惯:
1.为了避免变量混乱或被覆盖,对于局部变量的定义一定不要忘记加上var关键字;
  js函数的第一行开始定义该函数内用到的所有变量;
  不在for,if,while等块中定义变量;
  不在无须实例化的函数内使用this代替window去访问全局变量;
2.巧用匿名函数,减少命名冲突或变量污染;(把你的代码放在匿名函数里!那么,就不会和第三方的JavaScript冲突!)。将所有的代码封装到一个匿名函数中,并在它的定义结束后立刻执行它:
var str = 'tom';   
(function(){  
    str = 'jack'; 
})();  
alert(str);  //打印出jack 
再看一个例子:
var str = 'tom';   
(function(){  
    var str = 'jack';  
})();  
alert(str);  //打印出tom 
3.避免使用全局变量?
看你用那钟方式编程,如果用面向对象的方式来组织代码的话,全局变量是比较相对的;
对于喜欢用过程化方式编程的人,全局变量还是给他们带来很大的灵活性的。

参考:http://abruzzi.iteye.com/博客中的“javascript内核系列”

js变量作用域 相关博客:
http://shuxiang.iteye.com/blog/575268
http://lectery.iteye.com/blog/480401
http://muyu.iteye.com/blog/424372
http://lyang0000.iteye.com/blog/625912
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics