javascript作用域详解

日期:2018-03-31 08:56:14 类别:  Javascript

javascript从以前端网页特效,脚本,到现在可以开发服务器端应用,越来越多开发者重视,并且使用它了。

今天看看javascript中的作用域!

1)、作用域也叫执行环境(execution context)是JavaScript中一个重要的概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。在JavaScript中变量的作用域有全局作用域和局部作用域,全局变量是指变量没有在函数体内声明或者在函数内声明的时候没有带var,即表示拥有全局作用域,相反变量在函数内声明带var称为局部变量,拥有局部作用域。特殊的虽然函数参数不带var但它也属于局部变量。

 var a = 1; //全局变量
         function fn1( b ){ //局部变量
             var c = 2; //局部变量
             d = 3; //全局变量
        }

(2)、接下来介绍一下解析过程。浏览器有专门的一段程序用于解析JavaScript,暂且给他取个名字叫JavaScript解析工具,这个解析过程至少有两个过程(当然不仅仅有两个,像编译原理的词法分析什么的,这里不提):1.寻找目标(预解析)。包括var、function、参数等。 2.逐行解读代码。接下来通过实例来具体分析是怎么做的:

alert( a ); //undefined
         var a = 1;
         function fn (){
             alert( 2 );
         }

具体过程:

    1.寻找目标。包括var、function、参数等       a = undefined (所有的变量在正式运行代码之前,都会提前赋值一个值,即undefined)。       fn = function() { alert(2) } (所有函数在正式运行之前,都是整个函数块)     2.逐行解读代码。       解读代码时表达式会改变预解析中的值,如以上代码解读到第二行时,a = undefined 变为了 a = 1; 特殊的:如果预解析过程中遇到重名的,只留一个。如变量和函数重名了,就只留函数。再来一个例子说明

alert( b );  //function a() { alert( 4 ) };
  var b = 1;
  alert( b ); //1
  function b () {
              alert( 2 ); 
          } 
  alert( b ); //1
  var b = 3;
  alert( b ); //3
 function b (){
             alert( 4 );
         }
 alert( b ); //3

解析过程还是那两步,只是多了重名的情况。1.预解析后只留下 b = function b(){ alert(4) }。

2.逐行解读后,预解析中a的值变为3,若在代码的最后调用 b(), 则会在控制台报错。  

(3)JavaScript中没有块级作用域。先看一个例子:

if( true ){

         var a = 1;

 }

 alert( a );   //1

在一个 if 语句中定义变量 a。如果是在 C、C++等语言中,a会在 if 语句执行完毕后被销毁。但在JavaScript中,if 语句中的变量声明会将变量添加到当前的作用域(在这里是全局作用域)中。特别是在使用 for 语句时:

for( var i=0; i<10; i++ ){

   doSothing(i);

 }

 alert(i);  //10

对于块级作用域的语言来说,for语句初始化变量的表达式所定义的变量,只会存在于循环的环境中。而对于JavaScript来说,有for语句创建的变量 i 即使在for循环执行结束后,也依旧会存在于循环外部的作用域中。

(4)、函数是作用域,有预解析等过程,if for语句不是作用域。尽量不要在 if for中定义变量和函数调用,否则有浏览器问题:

alert(fn1);   //chrome,FF 弹出 undefine. ie 弹出整段函数(function fn19=(){alert( 123 )})

 if( true ){

     var a = 1;

function fn1(){

         alert( 123 )

     }

 }

作用域链  

  1. 当代码在一个环境中执行时,会创建变量对象的一个作用域链。它的作用是保证对执行环境有权访问所有变量和函数的有序访问。也就是说作用域链就像是一种绳索可以将各个作用域连接起来,已达到可以访问各个域中的变量,当然这种访问是要遵守一定的规则的,即局部作用域可以通过作用域链访问所有的全局作用域,但是全局作用域不能访问局部环境中的任何变量或函数。看下面的例子:


     var a = 1;

     function change{

             var b = 2;

             function swap(){

                 var c = b;

                 b = a;

                a = c;

     

                //这里可以访问a,b,c

             }

     

             //这里可以访问a和b,但不能访问c

             swap();

     }

     

     //这里只能访问a

     change();