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

时间:2023-03-08 22:25:44

本文为原创,转载请注明出处: 我所理解的javascript中函数的作用域和作用域链cnzt       文章:cnzt-p

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

写在前面

  一周木有更新了,今天终于攻克了自行车难关,非常开心,特意来一更~ (那些捂嘴偷笑的人我看到你们了快把嘴闭上我会假装没看见)。

  本文内容均基于个人理解,如有不认同,墙裂欢迎留言交流~~~

正文

作用域

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

 var a = 1;  // 表达式

 function func(){ a = a + 1; }; // 函数声明

 func(); // 函数执行

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

 var a;  // 变量声明

 function func(){ a = a + 1; }; // 函数声明

 a = 1;   //执行变量赋值
func(); // 函数执行 --> a=2

  

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

 //html文件中 script标签包裹的块
<script>
...
</script> //外部 javascript文件中最外层的块,一般包含init()
function init(){ ... }
...
init()

  另一类是当javascript碰到一个function时,这个function内部会形成一个它内部的作用域。如下:

/*相对于函数来说的作用域*/

...
//这里是函数外部作用域
...
function(){
//这里是函数内部作用域
// ...
}

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

 var a = 1;
var b;
var c;
function f(){
b = 2;
var d = 3;
console.log(a); //1
console.log(b); //
console.log(d); //3
}
f();
console.log(a); //
console.log(b); //
console.log(c); //undefined
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中找不到相应的变量时,向上(外部)一层一层寻找直到最外层,找到则引用,找不到则报错 -- 就是这么简单!

  

思考题

 var a = 10;
var b = 5;
function f(){
console.log(a);
var a = 20;
console.log(a);
var d = 30;
var ff = function(){a++; b++; d++; console.log(a); console.log(b); console.log(d);}
return ff;
} var c = f();
c();
f()();
c();

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

本文完。