码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript的作用域详解。

时间:2017-06-24 22:48:18      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:解决   经验   告诉   function   作用域   解析   上传   相同   命令执行   

     很多人学过JS吧,可能有大神一笑而过,本篇文章自我撰写,只适合新手不懂的同学们,大神请在2路公交车站左拐,也欢迎指点。

          

               我在几个月前是个连html是什么都不知道的高中生菜鸟,但是学了几个月之后,常常因为自己定义的一些函数没有作用而十分苦恼。

               我自己也去学过官方的作用域,但是感觉太肤浅,对于基础差的同学们(入此行皆学生)是个非常容易混淆的一种概念。

 废话不多说,首先讲原理,大家都知道JS是逐行执行,首先进入作用域只有有两种方式:

                     1.当看到script标签的时候,进入到作用域,也就是内置的<script></script>

                     2.当调用一个方法的时候,进入到作用域。比如上面代码的fn();

                          这两点切记!切记!

                          那么,什么是作用域?用通俗的话来说,就是开辟一个特定空间,将解析到的东西放在里面。

                           解析前,还有一个道理,叫做JS预解析?为什么叫“预”?就是没执行之前先扫描一遍,将所有的var 和function存到作用域的仓库里。扫描出来所有var的值都预先是undefined!

                我们首先进行预解析!

                 不多说,首先上第一题

 1 var a=100;
 2 
 3 function fn(){
 4      aert(a);
 5 
 6      var a=200;
 7  
 8      alert(a);
 9 }
10 
11 fn();
12 alert(a);
13 var a;
14 alert(a);
15 var a=300;
16 alert(a);

          这是第一题,大家可能有些人尝试着去看题目解析了,但是你知道解析的原理和顺序吗?光靠经验猜是没用的。计算机按照死命令执行,不会因为你用久了就知道你的心思去帮你完成:

通过预解析扫描全部var 和function,第1行,解析器看到了个var a ,就在仓库里定义 var a=undefined;

在第3行,解析到一个function fn(){...}  ,也丢到仓库里;继续,

在第11行,解析器跳过,前面提过了,解析器只会对var 和 function进行预解析,

到13行,又看到了个var a,这时重新定义,但是var a依旧是undefined,值不变,有些同学可能不懂,略作解释,前面提过了,所有在预解析里解析所有的var 都是未定义;同名直接覆盖,

后面没有var和function了,所以预解析结束,进行逐行执行

第1行,var a=100;这里我又要讲一个方法了,就是当js执行的时候,会找有没有+、-、*、/、++、--....如果有,就到预解析里去寻找对应的值进行修改变量var;这里a=100,有个“=”号,所以就去预解析仓库里修改var a=100;

第3行,函数,跳过。

               第11行,调用了上面的函数,有些同学是不是想告诉我答案?100?  NO NO NO,请看进入作用域的条件方式第二条!!!进入了函数!!重新定义另一个作用域,进入预解析,整个函数里是不是只有一个变量var ?  然后就屁颠屁颠的跑到仓库里去定义 var a=undefined;(因为有var,所有重新定义这个函数内的变量a,不会和外面的产生冲突)解析完毕,进行执行,这下你知道alert(a);为什么会执行undefined了吧?  继续,接下来看到了var a=200;然后去作用域的仓库里修改var a=200;的值,接下来的alert(a)毫无疑问,弹出来200;  这个函数作用域主要的难点在于概念,你可能看到解析方法简单,但是真执行的时候,你总是会忘记进入新的作用域是会重新定义这个新“仓库”的;

第12行,根据第1行已经修改的变量得出 alert是100;

第13行,var a;首先,他这也是定义,但是没有修改变量,所以变量a依旧是100;

第14行,毫无疑问,弹出100;

第15行,修改变量 变量a=300;

第16行,弹出300;

技术分享

技术分享

   以上附出图,希望同学们理解。

 

学计算机语言,最忌讳不学原理,可能前期你不会发觉,到后期,缺点就会慢慢展现出来;

 

还有第二题。。。

1 alert(a);
2 var a=1;
3 alert(a);
4 function a(){alert(a)};
5 alert(a);
6 var a=3;
7 alert(a);
8 function a(){alert(4)};
9 alert(a);

学过上文的同学们试着解下这道题,不要直接看答案,吸收过的东西才是自己的;

 

好,咱们来解决这道题;

首先预解析,进入作用域

第2行,添加var a=undefined;

第4行,添加function a(){alert(a)};

第6行,添加var a=undefined,但是已存在,覆盖不变;

第8行,添加function a(){alert(4)};这是重点,同名函数,覆盖第4行的数据,

所以现在这个作用域仓库里只有一条数据 :function a(){alert(4)};大家或许会很纳闷,还有var a=undefined呢?

这里向大家解释下,当函数名称和变量方法一样的时候,变量就会被隐藏!对!是隐藏,不是覆盖,不是删除!

开始逐行执行,

大家先猜猜第一行执行什么? 

 有人说是undefined,也有人想的是弹出4;。。。

结果是alert(   function a() {alert(4)});对,你没看错,它弹出的是一整个函数。没执行的函数,我当初也是这么懵的;

接下来第2行,重新修改 ,隐藏函数function;var a=1

第3行,弹出1;

第4行,你们第一个念头是不是重新覆盖?NONONO,只有在预解析的情况下,函数名称和变量名一样的情况下才会让变量隐藏,执行的时候,他们相互间是没有关系的

第5行,所以,弹出1;

第6行,修改值var a=3;

第7行,弹出3;

第8行,又来混淆我们的耳目了,前面提过,执行的过程中,函数是不会替换相同变量名的;只作为一个方法被调用;

第9行,弹出3;

技术分享

 

   是不是被绕的有点晕了,还有呢!来个比较简单的!

1 var a=1;
2 function fn1(){
3      alert(a);
4      var a=2;
5 }
6 fn1();
7 alert(a);

这道题自己做试试看吧。

 

然后我们开始,首先预解析

第1行 var a=undefined;

第2行 存储function fn1(){..}

解析完毕。

第1行,修改变量a=1;

第6行,进入作用域,开始预解析;

              找到var  得到 var a=undefined;

            开始处理,弹出undefined;

第7行,由于作用域只限制于嵌套,不含被嵌套,所以弹出1;

技术分享

 

但是。。我稍微修改下。你会么?

 

1 var a=1;
2 function fn1(){
3      alert(a);
4      a=2;
5 }
6 fn1();
7 alert(a);

学会自己思考,才能消化,成为自己的知识,

 

首先 老规矩,预解析;

第1行 ,得到var a=undefined;(再次声明:预解析里的var都是undefined,直到逐行执行js代码var a=?将其修改变量)

开始执行

第1行,得出var a=1;

 

第6行,进入作用域,由于fn1里没有var   ,但是,需要这个a的值所以,会请求向上查找!这里提起一个概念,函数内的请求只会去上级查找,也就是嵌套,比如一个员工,他想申请涨工资,只能先到小组组长申请,再到组长那,再到主管,再往上就是经理,CEO,一级没有就继续往上传。到CEO都没解决,那就只能(not a defined)没戏了;

所以fn1()会弹出上级的变量a的值,也就是alert(1);  接下来,是一个全局变量,什么是全局变量,意思是重新定义所有的变量a的值就是a=2;当然,后续执行程序的时候还是能通过var a=?进行修改的;

第7行,弹出2;

技术分享

 

 

觉得自己懂了?再来一发;

1 var a=1;
2 function fn1(a){
3      alert(a);
4      a=2;
5 }
6 fn1();
7 alert(a);

嘿嘿,知道该怎么做了吗? 我仅仅添加了个参数a;

 

最好自己思考下,毕竟学习的知识不是一下子就能消化的;

 

动手!

首先预解析;

第1行,得到var a=undefined;

第2行,存储一个函数;function fn1(a){...};

开始逐行执行;

第行,修改变量a的值;

第6行,调用,进入作用域,这里重头戏来了,这里要再提一个概念,参数的传参形式和var的赋值形式是一样的;意思就是,你参数填的什么(比如现在的fn1(a)),就直接相当于默认的var a(var a=undefined);只是还没传入值;接着解析,在下面也没能找到var,所以直接弹出undefined;接下来的a=2只是一个传递参数(谁让和参数重名呢?),不会进行全局变量;fn1()执行完;

第7行,第一行的var a=1没有改变值,所以弹出1;技术分享

 

 

 

好了,希望我讲的大家能接受,如有不好的地方,欢迎留言指正!本人虚心接受!

JavaScript的作用域详解。

标签:解决   经验   告诉   function   作用域   解析   上传   相同   命令执行   

原文地址:http://www.cnblogs.com/yuanziwen/p/7074580.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!