JavaScript的作用域详解。

很多人学过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;

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

时间: 2024-10-15 11:33:48

JavaScript的作用域详解。的相关文章

JavaScript 变量作用域 详解

变量作用域要点 - 在JavaScript中没有块级作用域,只有函数作用域 - 在函数体内,局部变量的优先级高于同名的全局变量 - 在全局作用域编写代码时可以不写var语句,但声明局部变量时必须使用var语句 - 函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,变量在声明之前已经可用JavaScript的这个特性被非正式的称为*声明提前* - 函数内的变量声明提前至函数体顶部,同时变量初始化留在原来的位置 - 但声明一个JavaScript全局变量时,实际上是定义了全局对象的一个属性

Javascript 严格模式详解

Javascript 严格模式详解 作者: 阮一峰 日期: 2013年1月14日 一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode).顾名思义,这种模式使得Javascript在更严格的条件下运行. 设立"严格模式"的目的,主要有以下几个: - 消除Javascript语法的一些不合理.不严谨之处,减少一些怪异行为; - 消除代码运行的一些不安全之处,保证代码运行的安全: - 提高编译器效率,增加运行速度

代码示例:一些简单技巧优化JavaScript编译器工作详解,让你写出高性能运行的更快JavaScript代码

告诉你一些简单的技巧来优化JavaScript编译器工作,从而让你的JavaScript代码运行的更快.尤其是在你游戏中发现帧率下降或是当垃圾回收器有大量的工作要完成的时候. 单一同态: 当你定义了一个两个参数的函数,编译器会接受你的定义,如果函数参数的类型.个数或者返回值的类型改变编译器的工作会变得艰难.通常情况下,单一同态的数据结构和个数相同的参数会让你的程序会更好的工作. function example(a, b) { // 期望a,b都为数值类型 console.log(++a * +

我看朴灵评注阮一峰的《JavaScript 运行机制详解:再谈Event Loop》

阮一峰和朴灵对我来说都是大牛,他们俩的书我都买过,阮老师的译作<软件随想录>和朴灵的<深入浅出node.js>.这个事情已经过了4个月了,所以我拿来讲应该也没啥问题. 这件事情是这样的,阮一峰在自己的博客写了篇文章<JavaScript 运行机制详解:再谈Event Loop>,然后朴灵看见了,发现了很多问题,然后在印象笔记又写了篇文章<[朴灵评注]JavaScript 运行机制详解:再谈Event Loop>,由于印象笔记现在已经不能访问了(尼玛也太烂了)

JavaScript 运行机制详解

JavaScript 运行机制详解——转载: 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. JavaScript的单线程,与它的用途有关.作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM.这决定了它只能是单线程,否则会带来很复杂的同步问题.比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另

javascript工具--控制台详解(转自 阮一峰博客)

javascript工具--控制台详解(转自 阮一峰博客) 大神这篇博客是写在2011年,主要介绍 "Firefox" 浏览器插件 "Firebug" 的操作,如今主流浏览器对控制台都已经提供了很好的支持.我自己用的最多是谷歌的 "chrome" 浏览器,下面也用 "chrome" 浏览器来调试. 一.显示信息的命令 console.log();  //控制台输入 网页中不会输出 console.info();  //一般信息

JavaScript对象类型详解

JavaScript对象类型详解 JavaScrtip有六种数据类型,一种复杂的数据类型(引用类型),即Object对象类型,还有五种简单的数据类型(原始类型):Number.String.Boolean.Undefined和Null.其中,最核心的类型就是对象类型了.同时要注意,简单类型都是不可变的,而对象类型是可变的. 什么是对象 一个对象是一组简单数据类型(有时是引用数据类型)的无序列表,被存储为一系列的名-值对(name-value pairs).这个列表中的每一项被称为 属性(如果是函

javascript 操作cookies详解

javascript 操作cookies详解 这段操作cookies的方法我使用很久了,但是一直一来没遇到什么问题,今天在做一个在第一个页面保存了cookies,第二个页面获取或者第三个页面获取的功能中,发现了方法的局限性,比如,第一个页面路径为 http://xxxxx/cyb-car2016/h5OfficeWorker/index,第二个页面路径为 http://xxxxx/cyb-car2016/h5AlertController/index,其中除了域名是一样之外,还有一个命名空间不一

[转]JavaScript异步机制详解

原文: https://www.jianshu.com/p/4ea4ee713ead --------------------------------------------------------------------------- 学习JavaScript的时候了解到JavaScript是单线程的,刚开始很疑惑,单线程怎么处理网络请求.文件读写等耗时操作呢?效率岂不是会很低?随着对这方面内容的了解和深入,知道了其中的奥秘.本篇文章就主要讲解一下JavaScript怎么处理异步问题. 一.同