菜鸟入门第四天——JS预编译

前言

今天我将带领兄弟们学习预编译,这是许多大厂或面试时会经常出现的问题。希望通过我的讲解,能让兄弟们有所收获。

什么是预编译

预编译(Precompile)是指在程序执行之前,将程序源代码或某些代码片段提前进行编译,以便在运行时能够更快地执行其主要目的是提高程序的执行效率和性能。

预编译分为两种,一种叫做函数预编译,另一种叫做全局预编译,函数预编译发生在函数执行的前,全局预编译发生在页面加载完成时。

函数预编译

话不多说,下面我将通过这个案例来帮兄弟们分析函数预编译过程。

js 复制代码
function fn(a){
    console.log(a); // function a() {}
    var a = 123
    console.log(a); // 123
    function a() {} // 函数声明
    console.log(a); // 123
    var b = function() {} // 函数表达式
    console.log(b); // function () {}
    function d(){}
    var d = a
    console.log(d); // 123
}
AO:{
    // a: undefined 1 function a() {}   123,
    // b: undefined function () {},
    // d: undefined function d() {} 123,
}
fn(1)

预编译发生在函数执行之前 (四部曲)

1.创建AO对象 (Action Object)

在函数执行前,JavaScript引擎会创建一个特殊的对象,叫做Action Object(AO)。这个对象用于存储函数内的局部变量、形参以及函数声明。

js 复制代码
AO:{

}

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

JavaScript引擎会扫描函数内部,找到所有的形参和变量声明。然后,它将这些变量声明和形参作为AO对象的属性名,初始值为undefined。

js 复制代码
AO:{
    a: undefined
    b: undefined
    d: undefined
}

3.将实参和形参值统一

js 复制代码
AO:{
    a: undefined -> 1
    b: undefined
    d: undefined
}

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

js 复制代码
AO:{
    a:undefined -> 1 -> function a(){} -> 123
    b:undefined -> function b(){}
    d:undefined -> function d(){} -> 123
}

代码已经分析完了,下面给大家来看看运行结果:

全局预编译

下面我将通过另外一个案例来帮兄弟们分析全局预编译过程。

js 复制代码
GO:{
    global: undefined 100,
    fn: function fn() {}
}
var global = 100
function fn() {
    console.log(global);
}
AO:{
    //由于函数内部没有形参和声明变量,也没有函数声明,所以AO对象内为空
}
fn()

预编译发生在全局(三部曲)

1.创建 GO 对象(Global Object)

全局预编译阶段开始时,JavaScript引擎会创建一个全局对象,通常称为Global Object(GO)。这个对象是全局作用域中的根对象。

js 复制代码
GO:{

}

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

引擎会扫描全局作用域,找到所有的变量声明,并将它们作为GO对象的属性名,初始值设置为undefined。

js 复制代码
GO:{
    global: undefined,
    fn: function fn() {} 
}

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

在全局作用域内,引擎还会找到函数声明,将函数名作为GO对象的属性名,同时将整个函数体赋给这个属性。

js 复制代码
GO:{
    global: undefined -> 100
    fn: function fn(){}
}

代码已经分析完了,下面给大家来看看运行结果:

结语

让我们通过这张图来分析一下JS预编译的过程

当JavaScript程序开始执行,会创建一个全局执行上下文(GO)并将其推入调用栈的底部。当程序调用一个函数,函数的执行上下文(包括变量环境、词法环境)被创建,并被推入调用栈的顶部。当函数执行完毕,它的执行上下文从调用栈的顶部弹出,控制权返回到调用该函数的上下文。如果函数内部调用其他函数,这些函数的执行上下文按照调用顺序被依次推入和弹出调用栈。

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax