2018-03-25

【修真院web小课堂】JS——预解析

大家好,我是IT修真院成都分院第11期的学员,一枚正直纯洁善良的WEB程序员 今天给大家分享一下,JS——预解析。

一、背景介绍

JAVASCRIPT解析机制是什么?

JavaScript解析过程分为两个阶段,一个是编译阶段,另外一个就是执行阶段。

编译阶段就是我们常说的JavaScript预解析(预处理)阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码。

在编译阶段JavaScript解释器借助执行环境把字节码生成机械码,并顺序执行。

二.具体执行的操作

1.var , FUNCTION声明的变量提升

首先,创建一个当前执行环境下的活动对象,然后将用 VAR 声明的变量设置为活动对象的属性(也就是将其添加到活动对象当中)并将其赋值为UNDEFINED,然后将 FUNCTION 定义的函数 也添加到活动对象当中。


var定义的aa,bb以及function定义的AA(),BB()都会被变量提升到window对象下面

2. 函数声明与函数表达式在预解析的区别

首先,我们知道解析器会对function定义的函数(也就是函数声明)在代码开始执行之前对其实行函数声明提升(function declaration hoisting),所以在函数声明之前调用该函数是不会在执行期间报错,但是函数表达式不同,函数表达式用 var 声明,也就是说解析器会对其变量提升,并对其赋值为undefined,然后在执行期间,等到执行到该var 变量的时候再将其变量指向一个function函数,所以在函数表达式之前执行该函数是会报错的。


3. function 覆盖


若定义了两个同名的函数,则在预解析期间后面一个会覆盖签名一个。

4. 预解析把变量或函数解析到其运行时的环境中

解析器将变量提升并不是将所有的变量都提升到window对象下面,其提升的原则是提升到变量运行的环境中去。

5. var 变量提升以及 function 函数声明提升

该点是对函数声明以及函数表达式进一步的说明,其实前面函数声明和函数表达式在预解析的不同表现,其主要的原因就是 var 和 function 两者不同的提升。这个问题从解析阶段到运行阶段来说明。首先,在解析阶段 var 后面的 AA 会被提升然后 AA 被定义为undefined,BB 也会被提升,而BB被提升后的内容就是整个 function 里面的内容,其实从浏览器的控制台我们可以看出一二。然后,整个解析过程完了就到了运行阶段,在运行阶段期间,当读到 AA() 的时候,其实就是将 AA 这个变量指向function(){}这个函数然后调用,而到了 BB() 的时候,就会从之前声明的函数中去查找该早已经声明的函数,然后直接调用。


这个例子就很好说明了 var 在运行阶段动态内建,而 function 在预解析阶段静态建立。

三、更多讨论

问题1:下图分别获取到此值是怎么得来的?

答:第一个AA()是因为函数声音才会提升整个函数,所以第一个AA()执行的是函数声明function AA(){};

第二个AA()是因为函数声明发生在预编译阶段;然后根据函数覆盖,所以执行函数表达式;

问题2、为什么这样写,第二个AA()执行的还是函数表达式?

变量在声明它们的脚本或函数中都是有定义的,变量声明语句会被提前到脚本或函数的顶部。但是,变量初始化的操作还是在原来var语句的位置执行,在声明语句之前变量的值是undefined。

理由同问题一,并不只是自上而下,发生了函数覆盖,而是因为预编译的作用,函数声明提升到了最前面,在执行阶段,函数声明已经编译过了所以不会再编译,然后被后面执行的函数表达式覆盖;

问题3、为什么第一个打印出来是undifined;而不是error;

因为预编译中的变量提升,此时第一个打印之前已经编译了var=undifined,只是var提升了,但值并没有跟着提升,此时还没有对var赋值而已,但并不会报错。

如下图所示这么写就会报错;

所以对于函数表达式,变量赋值是不会提前的,所以函数定义并没有被执行,所以函数表达式不能像函数声明那样进行函数声明提前。

你可能感兴趣的:(2018-03-25)