JavaScript中的预编译如何进行

110 篇文章 4 订阅
本文探讨了JavaScript中的预处理概念,包括变量声明、函数声明在全局和局部作用域的处理。通过实例解释了预编译过程中全局对象(GO)和活动对象(AO)的创建,以及如何影响代码执行。同时,通过一道面试题展示了预编译在变量查找和函数调用中的应用。
摘要由CSDN通过智能技术生成

预编译又称预处理,是整个编译过程最先做的工作,即程序执行前的一些预处理工作。主要处理#开头的指令。如拷贝#include包含的文件代码、替换#define定义的宏、条件编译#if等。

何时需要预编译:

总是使用不经常改动的大型代码体。

程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。

我们比较常见的问题:为什么人们会认为JS存在预编译,是JS的哪种行为让人们觉得它产生了预编译呢?让我们来简单聊一聊。

引入

在代码执行前,编译器会进行如下操作:

一 parse阶段

分词。就是将代码分成原子符号(token)

将token解析翻译成AST(语法生成树)。

二 analyze阶段

遇到声明语句,将会把声明传到作用域(scope)中创建绑定,分配内存并将变量默认设为undefined或函数体。

然后就可以执行代码啦,执行中途每次遇到赋值或者取值,都会从作用域中查找绑定。这样看,是不是有点“预编译”内味了?但是实际上还是称它为预处理更加贴切一点。接下来,让我们来了解一波看起来最像预编译的操作–第三步的干货。

“预编译”

我的老师在和我讲相关知识点前和我说过这么一个笑话:

面试时我因为这么一个问题挂了

var a = 100

function foo(){

console.log(a)

}

foo()

问:为什么输出a的值是100?

答:因为100赋值给了a。

老师说完我头昏脑涨,完全不明白笑点在哪,后来才知道这是在考察“预编译”这方面的知识。

总的来说,“预编译”可以分为

创建GO对象(global object) 发生在页面加载完成时

创建AO对象(activation object) 发生在函数执行前一刻

具体步骤如下:

全局预编译

  1. 创建GO对象

  2. 找变量声明,将变量声明作为GO对象的属性名,并赋值undefined

  3. 找全局里的函数声明,将函数名作为GO对象的属性名,值赋予函数体

局部预编译

  1. 创建一个AO对象

  2. 找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为undefined

  3. 将实参和形参统一

  4. 在函数体里找函数声明,将函数名作为AO对象的属性名,值赋予函数体

所以那个笑话里的面试问题我们应该这么回答:

首先,编译器创建一个GO对象

找到变量声明 var a

和函数声明 function foo(){}

将上面两个变量声明作为GO的属性名赋初值

GO{

a:undefined

foo:function(){}

}

然后运行第一行代码 a=100

在GO中将100赋值给a

再执行第五行代码运行foo函数

创建一个AO对象

在函数体内找变量声明和形参,(无)

再在函数体内找函数声明(无)

所以

AO{

}

完成后运行第三行代码,输出a

先在AO对象中寻找a的值,发现不存在,向外部作用域扩展,在GO对象中寻找a,发现a的值为100

输出100

当然,笑话里的题过于简单,但是能让我们清晰的了解到这个“预编译”的进行

下面,我们来看一道面试题简化版,练练手:

global = 100

function fn() {

console.log(global);

global = 200

onsole.log(global);

var global = 300

}

fn()

它的逻辑和输出结果是多少呢?通过一步步的分析我们可以知道具体的分析应该是这样的:

GO: {

global: undefined => 100,

fn: function() {}

}

global = 100 // 没有声明的变量默认为全局变量,也会放到GO中

function fn() {

console.log(global); // 输出undefined

global = 200

console.log(global); // 输出200

var global = 300

}

AO: {

global: undefined => 200 => 300

}

fn()

文章来源:网络 版权归原作者所

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系小编,我们将立即处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值