💡 前言:
JS 并非逐行直接执行,而是遵循 先预编译、后执行 的底层机制。执行上下文、调用栈、变量提升、块级作用域,是前端面试、笔试核心重难点,也是读懂 JS 代码执行逻辑的关键。
本文遵循 基础概念 → 底层原理 → 编译流程 → 真题实战 → 核心总结 逻辑,搭配8道大厂高频真题,从零吃透 JS 完整执行机制!
📌 一、核心基础:执行上下文(代码运行的载体)
所有 JS 代码运行,都必须依托 执行上下文对象,该对象包含三大核心模块,分工明确、互不冲突:
✨ 1. 变量环境
存储:var 声明的变量、function 函数声明
特性:支持变量提升、函数提升,无块级作用域,是 ES5 及之前的变量存储机制。
✨ 2. 词法环境
存储:let、const 声明的变量
特性(ES6 全新机制,修复 var 所有缺陷):
- ✅ 支持 块级作用域,作用域隔离彻底
- ✅ 无变量提升,遵循先声明后使用
- ✅ 存在 暂时性死区
- ✅ 禁止重复声明变量
✨ 3. 执行代码
JS 代码最终执行规则:从上到下、逐行顺序执行

💡 核心结论:变量环境、词法环境、执行代码,三者共同构成完整的执行上下文,支撑所有 JS 代码运行。
📌 二、底层调度:调用栈(V8引擎执行容器)
💡 调用栈是 V8 引擎用于 管理函数调用关系、控制代码执行顺序 的栈式数据结构,所有执行上下文都由调用栈统一管理。
✅ 核心执行规则(必背):
- 编译永远优先于代码执行,执行前会生成全局/函数执行上下文
- 所有执行上下文统一存入调用栈,栈顶指向 当前正在执行的上下文
- 函数执行完毕后,对应执行上下文自动出栈、销毁,释放内存
- 全局上下文常驻栈底,页面关闭后销毁

📌 三、核心流程:JS 预编译全过程
JS 核心机制:先编译预解析,后逐行执行,编译阶段决定变量提升、函数提升的最终结果,分为4个固定步骤:
✨ 步骤1:创建执行上下文
进入全局/函数作用域,自动生成全新执行上下文,初始化运行环境。
✨ 步骤2:扫描变量声明
遍历代码,收集所有 var 变量、函数形参 ,挂载到变量环境,默认赋值 undefined(变量提升原理)。
✨ 步骤3:同步形参实参(仅函数上下文)
将调用函数传入的实参值,赋值给对应形参,全局作用域无此步骤。
✨ 步骤4:扫描函数声明
收集所有 function 函数声明,整体提升存入变量环境,函数提升优先级高于变量提升。
📌 四、ES6 革新:let/const 底层机制
et、const 是为修复 var 历史 bug 诞生,核心差异在于存储环境和作用域规则:
✅ 核心特性汇总:
- 存储在 词法环境,依托调用栈管理作用域生命周期
- 拥有块级作用域,
{}内部变量无法向外穿透 - 无变量提升,存在暂时性死区,禁止先使用后声明
- 不允许同一作用域内重复声明变量
💡 设计意义:彻底解决 var 变量泄露、作用域混乱、重复声明、提升异常等问题。
📌 五、大厂真题实战(8道原题吃透执行机制)
结合上面所有理论,通过笔试原题实战,彻底搞懂变量提升、作用域隔离、上下文执行规则。
✨ 案例1:基础变量提升 + 函数提升
核心考点:编译阶段提前提升声明,实现先调用后定义
javascript
// 开发者书写代码
showName('极客时间')
console.log(myname)
var myname = 'yihao'
function showName(name) {
console.log(name);
var b = 1;
console.log('函数showName执行', name)
}
✅ V8 编译预处理(真实执行逻辑):
JavaScript
// 1. 变量提升(声明提升,值为undefined)
var myname;
// 2. 函数整体提升(完整函数体优先提升)
function showName(name) {
console.log(name);
var b = 1;
console.log('函数showName执行', name)
}
// 3. 从上至下逐行执行
showName('极客时间')
console.log(myname) // 输出 undefined
myname = 'yihao'
💡 结果:先打印「极客时间」,再打印 undefined。
✨ 案例2:变量与函数提升优先级对比
核心铁律:函数提升优先级 > var 变量提升
JavaScript
// 原生代码
showName();
console.log(myname);
myname = 'yihao';
console.log(func);
function func() {}
var func = 1;
✅ 编译提升后逻辑:
javascript
var myname;
var func;
function showName() {
console.log('函数showName执行');
}
// 同名函数提升覆盖变量
function func() {}
showName();
console.log(myname); // undefined
myname = 'yihao';
console.log(func); // 打印函数体
func = 1;
✨ 案例3:拼多多面试题(同名标识符冲突)
核心考点:形参、变量、同名函数的覆盖规则
JavaScript
var a = 1;
function fn(a) {
console.log(a);
var a = 2
function a() { }
var b = a;
console.log(a);
}
fn(3)
✅ 详细解析:
-
- 全局
a=1不影响函数局部作用域
- 全局
-
- 形参 a 初始接收实参 3
-
- 内部同名函数
a提升,覆盖形参,此时 a 为函数
- 内部同名函数
-
var a=2赋值,将函数覆盖为数字2
-
- 最终输出:打印函数 → 打印2
✨ 案例4:var 无块级作用域(变量泄露)
核心考点:var 仅区分函数作用域,不识别 {} 块级作用域
JavaScript
function varTest() {
var x = 1;
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2 内层变量覆盖外层,变量泄露
}
varTest();


✨ 案例5:let 块级作用域隔离
核心考点:词法环境实现块级隔离,杜绝变量泄露
JavaScript
function varTest() {
var x = 1;
if (true) {
let x = 2;
let b = 3;
console.log(x); // 2 块级局部变量
}
// console.log(b); // 报错:b 仅块内生效
console.log(x); // 1 外层var变量不受影响
}
varTest();
✨ 案例6:var/let 混合声明综合题
核心考点:变量环境、词法环境双重规则叠加
JavaScript
function foo() {
var a = 1;
let b = 2;
{
let b = 3;
var c = 4;
let d = 5;
console.log(a); // 1 上层变量可穿透块级
console.log(b); // 3 块级局部变量优先
}
console.log(b); // 2 外层b不受块内影响
console.log(c); // 4 var无块级隔离,全局穿透
// console.log(d); // 报错 d为块级私有变量
}
foo();



✨ 案例7:let 禁止重复声明规则
JavaScript
// let 严格禁止同作用域重复声明
let a = 1;
// let a =2; // 直接报错
// 变量与函数同名冲突
function a() {
}
✨ 案例8:综合报错+提升终极案例
JavaScript
// 综合测试:变量提升、重复声明、作用域冲突
// console.log(a);
// var a = 1;
// function a(){}
// let 不支持重复声明、无变量提升
let a = 1;
// let a =2;
function a() {
}
📌 六、核心知识点对比总结
- var/function(变量环境) :有变量提升、无块级作用域、可重复声明、易变量泄露
- let/const(词法环境) :无变量提升、块级隔离、禁止重复声明、存在暂时性死区
- 提升优先级:函数提升 > 变量提升
- 执行核心:先编译预解析,后逐行执行,调用栈统一管理所有上下文
📌 七、总结
- ✅ JS 执行流程:读取代码 → 预编译编译 → 逐行执行
- ✅ 执行上下文三要素:变量环境、词法环境、执行代码
- ✅ 调用栈:管理上下文生命周期,栈顶为当前执行代码
- ✅ var 归变量环境,let/const 归词法环境
- ✅ ES6 词法环境,彻底解决 var 所有历史缺陷
💬 文末互动
JS 执行机制是前端底层核心,也是大厂笔试高频考点!
✅ 掘金发布标签
JavaScriptJS执行机制变量提升前端面试大厂笔试执行上下文