
前言
在说预编译原理之前,我们先来了解两个名词。GO(global object):全局执行上下文;AO(activation object): 活跃对象,函数执行上下文。
预编译的过程跟这两个东西密切相关,其过程可归纳为两步:
1.检查通篇的语法错误;
2.解释一行,执行一行。
AO
我们先看下面这个例子,看你认为的结果和实际结果相差多少:
1 | function test(a){ |
看到结果之后是不是很震惊,跟你想想的完全不一样。这是为什么呢?当然跟我们前面提到的AO对象有关啦。在函数内部程序是按照AO的流程进行编译和执行的,且看AO执行流程:
1.寻找形参和变量声明;
2.实参值赋值给形参;
3.找函数声明;
4.执行,赋值。
我们现在依照这个流程来走一下上面这段程序。
1、首先我们寻找函数内部的形参和声明的变量,有变量a:undefined, 变量b: undefind
2、第二步将实参值赋值给形参。a变成了2
3、然后寻找函数声明,a: function a() {}, d: function d(){}
4、最后执行函数并赋值。a = 1, b = function () {} ,此时你是不是在想a现在不是等于1了吗,应该前三个都打印1呀,但是你忽略了第四步的要点,执行并赋值,因为第一行的console.log(a) 在未赋值之前,此时a的值在第三步中已经变成了函数**function a() {},所以此时打印function a() {}**。
上面的四条你如果觉得可以用以有点难理解,请结合以下结构阅读:
1 | AO = { |
注意: 函数执行完成以后,AO是要销毁的,AO是一个即时的存储容器
趁热打铁,在来一道题:
1 | function test(a,b) { |
使用AO图解
1 | AO = { |
到这里是不是对预编译过程是不是有了清晰的理解了。
GO
同样先上一道例子:
1 | var a = 1; |
很多人可能知道这里会打印1,但是他无法说服自己为什么会打印1,而不是打印function a(){},甚至是2。
我们先看看全局上下文js的预编译过程:
1.找变量声明;
2.找函数声明;
3.执行,赋值。
现在用这三步流程来解析以下上面的代码块
1、找到变量声明a,此时值为undefined;
2、然后找到函数声明a,此时值为function a(){};
3、最后执行代码块,并赋值,此时a = 1。
下面用GO结构表示
1 | GO = { |
很多代码块我们可能只知道结果,但是不知道为什么是这样的结果,当我们弄清楚了预编译的过程,就很容易知道js代码块执行过程到底发生了什么。
基础夯实
看了上面的解释,你可能以为你掌握了预编译过程,那么请你做做下面的几道题,看看有几道题能答对呢(先别着急看后面答案和在浏览器中运行哟)。
例一:
1 | var b = 3; |
1 | GO = { |
例二:
1 | a = 1; |
1 | GO = { |
例三:
1 | function test(){ |
1 | GO = { |
例四:
1 | function test(){ |
1 | AO = { |
例五:
1 | function test() { |
1 | AO = { |
例六:
1 | a = 1; |
1 | GO = { |
- Post title: JS预编译
- Create time: 2021-01-09 13:15:00
- Post link: 2021/01/09/预编译/
- Copyright notice: All articles in this blog are licensed under BY-NC-SA unless stating additionally.