JS当中一个变量的作用域

js中定义变量加var和不加var的区别

在方法内,加var为局部变量,不加var则是全局变量

文章转载http://blog.csdn.net/beijiguangyong/article/details/8301707点击打开链接

在JS当中一个变量的作用域(scope)是程序中定义这个变量的区域。变量分为两类:全局(global)的和局部的。其中全局变量的作用域是全局性的,即在JavaScript代码中,它处处都有定义。而在函数之内声明的变量,就只在函数体内部有定义。它们是局部变量,作用域是局部性的。函数的参数也是局部变量,它们只在函数体内部有定义。

我们可以借助JavaScript的作用域链(scope chain)更好地了解变量的作用域。每个JavaScript执行环境都有一个和它关联在一起的作用域链。这个作用域链是一个对象列表或对象链。当JavaScript代码需要查询变量x的值时(这个过程叫做变量解析(variable name resolution)),它就开始查看该链的第一个对象。如果那个对象有一个名为x的属性,那么就采用那个属性的值。如果第一个对象没有名为x的属性,JavaScript就会继续查询链中的第二个对象。如果第二个对象仍然没有名为x的属性,那么就继续查询下一个对象,以此类推。如果查询到最后(指顶层代码中)不存在这个属性,那么这个变量的值就是未定义的。

以上的过程并不是我们所熟悉的顺序结构,但大致与顺序结构类似只不过是将作用域当作一个整体来看待而已。整个过程如上图所示

JS作用域实例

代码一(平淡的不能再平淡的代码)

[javascript]  view plain  copy
  1. var i=10;   
  2. function a() {   
  3.     alert(i);   
  4. };   
  5. a();  

代码二 

[javascript]  view plain  copy
  1. var i=10;   
  2. function a() {   
  3.     alert(i);   
  4.     var i = 2;   
  5. };   
  6. a();   

根据“多年”的编程经验你可能觉得这两个代码输出是一样的,但是事实却是第一个代码正常输出了变量的值----10,而第二个代码输出的却是undefined。也许很多人理解不了,但是根据前面的作用域链的图我们就很好理解了。

作用域链图中很明确的表示出:在变量解析过程中首先查找局部的作用域,然后查找上层作用域。在代码一的函数当中没有定义变量i,于是查找上层作用域(全局作用域),进而进行输出其值。但是在代码二的函数内定义了变量i(无论是在alter之后还是之前定义变量,都认为在此作用域拥有变量i),于是不再向上层的作用域进行查找,直接输出i。但是不幸的是此时的局部变量i并没有赋值,所以输出的是undefined。

《JavaScript权威指南》中提出的“没有块级作用域”实际上就是上述的意思。很多时候认为懂了、理解了,其实没有懂,细细的研究一番之后看回过头来再书中那加粗的文字,顿时恍然大悟,其实人家书里说的挺清楚的嘛!

代码三 某知名公司笔试题

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.     var a,b;  
  3.     (function(){  
  4.         alert(a);  
  5.         alert(b);  
  6.         var a = b = 3;  
  7.         alert(a);  
  8.         alert(b);  
  9.     })();  
  10.         alert(a);  
  11.             alert(b);  
  12.     </script>  

结果输出 undefined undefined 3 3 undefined 3

代码等价于

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.     var a,b;  
  3.     (function(){  
  4.         alert(a);  
  5.         alert(b);  
  6.         var a = 3;  
  7.         b = 3;  
  8.         alert(a);  
  9.         alert(b);  
  10.     })();  
  11.         alert(a);  
  12.         alert(b);  
  13.     </script>  

这主要是Js中没有用var声明的变量都是全局变量,而且是顶层对象的属性。

作用域链说明

代码四:

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.         name="Hello";    
  3.         function t(){    
  4.             var name="world";    
  5.             function s(){    
  6.                 var name="welcome";    
  7.                 console.log(name);    
  8.             }    
  9.             function ss(){    
  10.                 console.log(name);    
  11.             }    
  12.             s();    
  13.             ss();    
  14.         }    
  15.         t();   
  16.     </script>  

函数输出welcome world

当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显

name是"welcome"。

但执行ss()时,作用域链是: ss()->t()->window,所以name是”world"

代码五:一个很容易犯错的例子:

[html]  view plain  copy
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"  >  
  3. <head>  
  4.     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>  
  5.     <title>ajax</title>  
  6.     <style type="text/css">  
  7.     </style>  
  8.     <script type="text/javascript">  
  9.        function buttonInit(){    
  10.             for(var i=1;i<4;i++){    
  11.                 var b=document.getElementById("button"+i);    
  12.                 b.addEventListener("click",function(){ alert("Button"+i);},false);    
  13.             }    
  14.         }    
  15.         window.onload=buttonInit;    
  16.     </script>  
  17. </head>  
  18. <body>  
  19. <button id="button1">Button1</button>    
  20. <button id="button2">Button2</button>    
  21. <button id="button3">Button3</button>   
  22. </body>   
  23. </html>  

当文档加载完毕,给几个按钮注册点击事件,当我们点击按钮时,会弹出什么提示框呢?

很容易犯错,对是的,三个按钮都是弹出:"Button4",你答对了吗?

当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,

所以弹出”button4“。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值