【修真院web小课堂】JS——预解析
大家好,我是IT修真院成都分院第11期的学员,一枚正直纯洁善良的WEB程序员 今天给大家分享一下,JS——预解析。
一、背景介绍
JAVASCRIPT解析机制是什么?
JavaScript解析过程分为两个阶段,一个是编译阶段,另外一个就是执行阶段。
编译阶段就是我们常说的JavaScript预解析(预处理)阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码。
在编译阶段JavaScript解释器借助执行环境把字节码生成机械码,并顺序执行。
二.具体执行的操作
1.var , FUNCTION声明的变量提升
首先,创建一个当前执行环境下的活动对象,然后将用 VAR 声明的变量设置为活动对象的属性(也就是将其添加到活动对象当中)并将其赋值为UNDEFINED,然后将 FUNCTION 定义的函数 也添加到活动对象当中。
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() 的时候,就会从之前声明的函数中去查找该早已经声明的函数,然后直接调用。
三、更多讨论
问题1:下图分别获取到此值是怎么得来的?
答:第一个AA()是因为函数声音才会提升整个函数,所以第一个AA()执行的是函数声明function AA(){};
第二个AA()是因为函数声明发生在预编译阶段;然后根据函数覆盖,所以执行函数表达式;
问题2、为什么这样写,第二个AA()执行的还是函数表达式?
理由同问题一,并不只是自上而下,发生了函数覆盖,而是因为预编译的作用,函数声明提升到了最前面,在执行阶段,函数声明已经编译过了所以不会再编译,然后被后面执行的函数表达式覆盖;
问题3、为什么第一个打印出来是undifined;而不是error;
如下图所示这么写就会报错;