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


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

    先看片段js代码如下:

    1          < script type="text/javascript" >
    2 
    3              console.log(a);
    4              var a = "hello world!";
    5 
    6              console.log(b);
    7              b = "你好,世界!";
    8 
    9         < /script >
    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定义的,所以没有,读取一个没有的变量,当然就报错了。

          

    我是签名内容
  • 相关阅读:
    Java IO总结
    Tomcat处理一个HTTP请求的过程
    Tomcat的web项目部署方式
    Tomcat性能调优
    jquery基础知识汇总
    Javascript中的正则表达式
    HTTP首部
    HTTPS
    Javascript中关于cookie的那些事儿
    HTTP请求方法详解
  • 原文地址:https://www.cnblogs.com/litianci/p/4954116.html
Copyright © 2020-2023  润新知