javaScript变量之作用域

javascript变量的作用域一直都是js程序员最困扰的难点之一。先通过概要来过一遍涉及到的知识。

一、全局变量

     全局变量包含:1.在函数体外定义的变量

                                 2.在函数体内部定义的无var变量(很多人很容易的误认为在函数体内定义的所有变量都是局部变量,这里需特变注意!)

     全局变量可以在任何位置被调用。

二、局部变量

      局部变量包含:1.在函数内部使用Var声明的变量

                                  2.函数的参数变量

      局部变量只能在当前函数体内部被调用。

三、优先级(符合就近原则)

      1.局部变量高于同名全局变量

      2.参数变量高于全局变量

      3.局部变量高于同名参数变量

四、特性

        1.忽略块级作用域

        2.全局变量是全局对象的属性

        3.局部变量是调用对象的属性

        4.作用域链:1)内层函数可访问外层函数局部变量

                                2)外层函数不能访问内层函数局部变量

        5.生命周期:1)全局变量:除非被显示删除,否则一直存在

                                2)局部变量:自声明起至函数运行完毕或被显示删除

                                3)回收机制:标志清楚+引用计数

接下来我们直接上代码,通过图示分析代码切身体会全局变量和局部变量的作用域。

 

<script type="text/javascript">
 	    var a = 8;
 	    var b = true;
 	    
 	    function test()
 	    {
 	    	alert(a);
 	    	alert(b);
 	    	b=false;
 	    	alert(b);
 	    	
 	    	var a = 20;
 	    	alert(a/2);
 	    	alert(++Math.PI);
 	    	alert(Math.PI++);
 	    }
 	    
 	    test();
 	
 	</script>

问题:a、b都是全局变量,但是第一个alert的结果却是defined,第二个的结果是true?

换句话说,b可以找到外面定义的全局变量,为什么a不能?

前面的概要中提到,局部变量的优先级大于全局变量。当js引擎在当前作用域(这个例子指test()函数体内)找不到此变量时,它就会往外但包含当前作用域的作用域找。

在这里我简单阐述一下关于js的作用域链的基本原理:

javascript需要查询一个变量时,首先会查找作用域链的第一个对象,如果第一个对象没有定义,则继续查找第二个对象……依次类推。

存在一个问题:当前的作用域中这个变量存在吗?

javascript是一种解释型语言,基本分为两个阶段:编译器与运行期。

在编译阶段,它是用函数来划分作用域,然后逐层为其以var声明的变量和函数的定义开辟内存空间,然后再对var变量进行特殊处理,统一赋初始值为undefined。

下面通过图片来看看以上例子编译后各个变量与作用域的关系:

分析:由上图我们知道当前网页拥有两个a,一个b,一个test函数。如果在运行期用到除此以外的东西,如X函数或y变量啦,都会报未定义错误(用eval等非正常手段生成变量与函数的情况除外),此外,它们最多出现未赋值警告。

javascript的运行期是在为var变量与函数定义分配空间后立即执行,并且是逐行往下执行的。

  • 第1行它为外围作用域的a赋值为100
  • 第2行它为外围作用域的b赋值为true
  • 第3行进行test的作用域
  • 第4行就立即调用test作用域的a,这时它还没有来得及赋值呢!不过它已经声明过了,因此默认为其赋值为undefined(在预编译阶段,见图),于是alert为undefined
  • 第5行就调用b时,JS引擎发现test的作用域内没有b,往test作用域外找,发现b了,而b在第二行就赋值为true,于是alert为true。
  • 第6行为一个赋值操作,把外围的b变量改赋为false。于是到第7行时,alert为false。剩下的代码同理。
讲到这里可能还是有小伙伴不能理解为什么有两个a,而只有一个b,下面再来个小测试:

以上例子的代码的第6行

  b=false;
改为:
  var b=false;
结果:第5行:alert(b)也变成了undefined

我们再来看看代码修改后编译出来的各个变量与作用域的关系:


这下恍然大悟了吧!在编译阶段,js引擎并不是和运行时一样按代码由第一行往下编译的,而是按var变量与函数定义分配空间,然后按顺序执行。在alert(a)、alert(b)时并未赋值,但是在编译时,在test()函数中已经声明过了,故结果为undefined。

掌握编译期为var变量与函数定义分配空间这一原理后,许多问题就会迎刃而解。

最后小结一下:

1.JavaScript的变量作用域是基于其特有的作用域链的。
2.函数体内部,局部变量的优先级比同名的全局变量高。
3.javascript没有块级作用域(在javascript中,函数不仅在块中有定义,在整个函数都有定义。)
4.函数中声明的变量在整个函数中都有定义。
(如果函数内部有定义变量,即使在定义之前输出也会先执行后面定义语句,然后判断输出结果.声明的变量在整个函数中都是起作用的。)
5.未使用var关键字定义的变量都是全局变量。
6.全局变量都是window对象的属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值