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

先看片段js代码如下:

          < script type="text/javascript" >

              console.log(a);
var a = "hello world!"; console.log(b);
b = "你好,世界!"; < /script >

开始的输出结果很出乎意料,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定义的,所以没有,读取一个没有的变量,当然就报错了。

Javascript预解析、作用域、作用域链的更多相关文章

  1. javascript预解析和作用域

    JavaScript解析过程分为两个阶段: 一是:编译阶段.就是JavaScrip预解析阶段,在这个阶段JavaScript解析器将完成把JavaScript脚本代码转换到字节码; 二是:执行阶段.在 ...

  2. JavaScript 之有趣的函数(函数声明、调用、预解析、作用域)

    前言:“函数是对象,函数名是指针.”,函数名仅仅是指向函数的指针,与其他包含函数指针的变量没有什么区别,话句话说,一个函数可能有多个名字. -1.函数声明,function+函数名称.调用方法:函数名 ...

  3. JavaScript 预编译与作用域

    JavaScript 预编译与作用域 JavaScript 预编译的过程和作用域的分析步骤是 JS 学习中重要的一环,能够帮助我们知道代码的执行顺序,更好理解闭包的概念 预编译 JavaScript ...

  4. JavaScript预解析

    定义:JavaScript"预解析",可以理解为把变量或函数预先解析到它们被使用的环境中. 通俗点讲,即认为浏览器在正式运行JavaScript代码前, 第一步,会预先根据关键字v ...

  5. JavaScript 预解析机制

    首先我们来看一段代码: <script> console.log(a); var a = 10; </script> 此时运行结果为   为什么会显示undefined呢?这就 ...

  6. js---07 js预解析,作用域---闭包

    js解析器首先不会逐行读代码,这是第二部了. 首先 根据var找到变量,根据function找函数,找到变量var a = 1,js解析器只会读取等号前面的var a,并把a设置值未定义,并不会读取等 ...

  7. js的预解析和作用域

    预解析指的就是,在js文件或者script里面的代码在正式开始执行之前,进行的一些解析工作.这个工作很简单,就是在全局中寻找var关键字声明的变量和通过function关键字声明的函数. 1.寻找 v ...

  8. javascript 预解析

    内容来源:http://www.cnblogs.com/TomXu/archive/2011/12/28/2286877.html JavaScript中,你可以在函数的任何位置声明多个var语句,并 ...

  9. 轻松搞定javascript预解析机制(搞定后,一切有关变态面试题都是浮云~~)

    hey,guys!我们一起总结一下JS预解析吧! 首先,我们得搞清楚JS预解析和JS逐行执行的关系.其实它们两并不冲突,一个例子轻松理解它们的关系: 你去酒店吃饭,吃饭前你得看下菜谱,点下菜(JS预解 ...

随机推荐

  1. jQuery自带的一些常用方法总结

    jQuery自带的一些常用方法总结 这篇文章主要介绍了jQuery自带的一些常用方法总结,包括$.trim .$.contains.$.each.$.map.$.inArray.$.extend等,需 ...

  2. Apache 相关配置

    1. HTTP缓存设置 ExpiresActive On #ExpiresDefault 设置全局缓存时间,将导致一些get请求不能连续执行 #ExpiresDefault "access ...

  3. C#笔记(Hex转JPG)

    由于最近需要用SD卡记录摄像头拍的图像,记录的文件格式十六进制的(例如:0xf0就是对应图像中的八个像素点)需要做一个SD卡上位机来将十六进制文件转换成JPG图像格式,方便对图像的分析. 总体的思路是 ...

  4. POJ1700:Crossing River(过河问题)

    POJ1700 题目链接:http://poj.org/problem?id=1700 Time Limit:1000MS     Memory Limit:10000KB     64bit IO ...

  5. python 深拷贝和浅拷贝浅析

    简单点说 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.id会变化2. copy.deepcopy 深拷贝 拷贝对象及其子对象.id会变化 >>> im ...

  6. LRU 算法简单实现

    在学习很多服务器软件中,当内存不够,而需要淘汰内存的时候,一般会使用LRU算法,便产生了浓厚的兴趣.在学习操作系统的过程中发现LRU在系统中用寄存器和栈来实现.所以我就尝试着学习用栈来解决LRU的问题 ...

  7. Http Request Process

    Request---------------->IIS(w3wp.exe)--------------->CLR(AppDomain)-------------------->ASP ...

  8. winPcap_3_获取设备列表

    获取设备列表 int pcap_findalldevs_ex ( char * source, //The 'source' is a parameter that tells the functio ...

  9. 一个强大的LogParser的UI工具--logparserlizard简介(开源IIS日志分析工具)

    原文地址:http://blog.csdn.net/downmoon/article/details/4509513 日志分析,特别是IIS日志,一般人都会想到LogParser工具,的确很强.但是命 ...

  10. SRM475 - SRM479(1-250pt,500pt)

    SRM 475 DIV1 300pt 题意:玩游戏.给一个棋盘,它有1×n(1行n列,每列标号分别为0,1,2..n-1)的格子,每个格子里面可以放一个棋子,并且给定一个只含三个字母WBR,长度为n的 ...