热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Javascript预解析、作用域、作用域链

最近在看js的一些资料,总结一下昨晚看到的js作用域方面的知识,不准确的地方希望留言指正!先看片段js代码如下:1<scripttypetextjavascrip

最近在看js的一些资料,总结一下昨晚看到的js作用域方面的知识,不准确的地方希望留言指正!

先看片段js代码如下:

 

1          
View Code

 开始的输出结果很出乎意料,firebug调试输出结果如下:

console.log(a);

输出:undefined

console.log(b);

 ReferenceError: b is not defined    思考:为什么定义变量在后,输出在前,而第一个输出a的地方没有报错,输出了“undefined”,而同样是先输出后定义的b,就报错了呢?

一、浏览器预解析

      浏览器是一个综合的软件,可以打开txt文本、照片、甚至符合格式的视频拖拽进去也能播放,也就是说浏览器支持各种格式的文件解析,具体的原理我们不用知道,需要知道的是,浏览器有一个专门负责解析js语句的东西,我们姑且叫做“js解析器”。

      在js解析器遇到script标记后,就启动解析器解析我们的js代码,这个解析过程中包括很多步骤,比如语法检查、垃圾回收...等等很多,但是其中有2点和我们今天说的作用域有关系,分别是”预加载“和”逐步解析“。

 

 1、js预加载

      当浏览器来执行我的js代码时,并不是一上来就开始一行行的执行我们的代码,而是在执行前有一个“预加载”的操作,预加载做了什么事情呢?

      1> 在当前域中,找到已var 开头的变量,function定义的函数,和参数,并将其提取出来,放到“仓库”中。

      2>将var定义的变量保存起来后,给其赋值为:undefined。需要主意的时候,预加载的时候,不会执行变量后面的表达式,只是单纯的提取出变量名,然后给其值undefined

      3>将function定义的函数名字提取出来,给其赋值为当前函数体,因为js解析器也不知道函数里面有什么东西,所以讲整个函数直接赋值给当前函数名称。

      4>讲参数也提取到“当前域”中,和var 类似,“当前域”这个下面会讲到。

      上面是js预加载做的事情,简单的说,在当前域中(先可以理解为script中的代码)找到var funciton 和参数这三样东西,然后提取出来放到仓库中,第一步完成。

2、逐步解析

 当js预加载完成后,开始执行第二步,逐步解析,通俗的说也就是一行一行的读取代码。我们已第一个代码片段为列子说明。

当预解析后,找到了var定义的变量,只有a是var定义,就把a放在仓库中,定义为undefined。第一步完成后,执行第二步,逐行执行代码。一上来第一行就是:console.log(a),

当读取到变量a的时候,浏览器就到仓库中去找a,因为经过了预解析,在执行代码前已经把a存起来了,并且赋值为undefined了,所以找打了a并且输出了他的值:undefined。

继续往下,读到了表达式 var a = "hello world!"; 同理,找到仓库中的a,并且赋值,记住表达式可以更改仓库中的值。然后继续往下走,读取b的时候,因为仓库中并没有存到变量b,因为他不是var定义的,所以没有,读取一个没有的变量,当然就报错了。

 

 

 

 

 

      


推荐阅读
author-avatar
好学的程序员
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有