我所理解的javascript中函数的做用域和做用域链

本文为原创,转载请注明出处: cnzt       文章:cnzt-pjavascript

 http://www.cnblogs.com/zt-blog/p/6654308.htmlhtml

写在前面java

  一周木有更新了,今天终于攻克了自行车难关,很是开心,特地来一更~ (那些捂嘴偷笑的人我看到大家了快把嘴闭上我会伪装没看见)。函数

  本文内容均基于我的理解,若有不认同,墙裂欢迎留言交流~~~spa

 

正文code

做用域htm

  简单来讲,javascript中有变量和函数的声明/定义,有变量赋值和函数的执行 ,且遵循先声明后执行原则,举个例子:blog

1 var a = 1;  // 表达式
2 
3 function func(){ a = a + 1; }; // 函数声明
4 
5 func(); // 函数执行

  上面的代码等同于下面这个:ip

1 var a;  // 变量声明
2 
3 function func(){ a = a + 1; }; // 函数声明
4 
5 a = 1;   //执行变量赋值 
6 func(); // 函数执行 --> a=2

  

  理解了先声明后执行原则以后,再来看做用域部分。简单来讲,javascript的做用域分两类,一类是最外层做用域,如javascript标签包裹起来的块,或者常见的包含init()的块,以下:作用域

1 //html文件中 script标签包裹的块
2 <script>
3  ... 4 </script>
5 
6 //外部 javascript文件中最外层的块,通常包含init()
7 function init(){ ... } 8 ... 9 init()

  另外一类是当javascript碰到一个function时,这个function内部会造成一个它内部的做用域。以下:

/*相对于函数来讲的做用域*/ ... //这里是函数外部做用域
... function(){ //这里是函数内部做用域
   // ... 
}

  第一次敲桌子--内部做用域能够访问外部做用域的值,反之行不通!好了,知道了这两类做用域后,再来边举个栗子边梳理做用域这个东西,栗子以下:

 1 var a = 1;  2 var b;  3 var c;  4 function f(){  5    b = 2;  6    var d = 3;  7    console.log(a);     //1 
 8    console.log(b);     //2
 9    console.log(d);     //3 
10 } 11 f(); 12 console.log(a);   //1
13 console.log(b);   //2
14 console.log(c);   //undefined
15 console.log(d);   //报错: d is not defined

 

  上面的栗子已经注释给出告终果,看到输入的结果以为正常么?(我好像问了句废话。。。)我仍是按照先声明后执行的原则来看下,首先,从上到下,声明了变量a,b,c,函数f,接着执行了a=1,执行函数f,这里第二次敲桌子啦敲桌子!!-- 执行f的时候发生了什么呢?不记得的翻上去看下,首次敲桌时说过了函数内部会造成新的内部的做用域。咱们来看下这个做用域,首先声明d,而后执行b=2,d=3,console.log(a),第一次敲桌子的时候说了内部做用域能够访问外部做用域的值,so这里a输入为1,接下来b和d都在函数内部赋过值了,因此console.log(b)和console.log(d)分别输出2和3。至此,f已经执行完了(下划线这部分),继续,console.log(a)这里a也已经赋过值会输出1,console.log(b) -- 第三次敲桌子啦!!!--b声明在外部做用域,赋值在f内部做用域,那么这个赋值的结果在外部做用域还生效么?答案显而易见,生效的,输出2(由于外部声明了,这个变量就一直存在,其余地方的赋值对其均有效)。再而后console.log(c) -- 第四次敲桌子!!!!c只是声明了而已,并无赋值,所以输出undefined。最后console.log(d) -- 第五次敲桌子!!!!!d为啥会报错呢?回头看首次敲桌时是怎么说的,“反之行不通”,即:函数外部不能访问其内部定义的变量!再回来看d,d只是在f内部定义了,而外部并无权限访问它,因此此次报错d is not defined...

  /*注意区分undefined 和 d is not defined,一个未赋值,一个根本未声明过。*/ 

 

做用域链

  看上面栗子中的5,7,8行,分别用到了a和b两个变量,这两个变量在f中声明了么?并无,那为何还能输出正确的值呢?做用域链就在这时候登场了。f中找不到相应的变量时,向上(外部)一层一层寻找直到最外层,找到则引用,找不到则报错 -- 就是这么简单!

  

思考题

 1 var a = 10;
 2 var b = 5;
 3 function f(){
 4     console.log(a);
 5     var a = 20;
 6     console.log(a);
 7     var d = 30;
 8     var ff  = function(){a++; b++; d++; console.log(a); console.log(b); console.log(d);}
 9     return ff;
10 }    
11 
12 var c = f();
13 c();
14 f()();
15 c();

好好想一想这个思考题,注意return的部分,三思然后F12哦~~~

 

本文完。

相关文章
相关标签/搜索