JavaScript篇:解密JS执行上下文:代码到底是怎么被执行的?

大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了常见的前端开发技术,我还擅长3D开发,熟练使用Three.js进行3D图形绘制,并在虚拟现实与数字孪生技术上积累了丰富的经验,特别是在虚幻引擎开发方面,有着深入的理解和实践。

我一直认为技术的不断探索和实践是进步的源泉,近年来,我深入研究大数据算法的应用与发展,尤其在数据可视化和交互体验方面,取得了显著的成果。我也注重与团队的合作,能够有效地推动项目的进展和优化开发流程。现在,我担任全栈工程师,拥有CSDN博客专家认证及阿里云专家博主称号,希望通过分享我的技术心得与经验,帮助更多人提升自己的技术水平,成为更优秀的开发者。

技术qq交流群:906392632

大家好,我是小杨,一个和JS相爱相杀6年的前端工程师。今天我要带大家揭开JavaScript代码执行的神秘面纱,保证让你看完后恍然大悟:"原来我的代码是这样跑的!"

一、执行上下文:代码的"舞台"

想象一下,JS引擎就像个剧场,每次函数调用就像一场新的演出。而执行上下文就是这个演出的"舞台",决定了哪些"演员"(变量和函数)可以上场。

先看个简单例子:

javascript 复制代码
function sayHello() {
    let me = '小杨';
    console.log(`大家好,我是${me}`);
}
sayHello();

当调用sayHello()时,JS就会创建一个新的执行上下文。

二、执行上下文的"人生三阶段"

每个执行上下文都会经历三个阶段:

  1. 创建阶段:准备舞台

    • 创建变量对象(VO)
    • 建立作用域链
    • 确定this指向
  2. 执行阶段:正式演出

    • 变量赋值
    • 函数调用
    • 执行代码
  3. 销毁阶段:演出结束

    • 出栈等待垃圾回收

三、变量提升的真相

来看个经典例子:

javascript 复制代码
console.log(me); // undefined
var me = '小杨';
console.log(me); // '小杨'

为什么不会报错?因为在创建阶段,变量声明会被提升,但赋值不会。

小杨踩坑记

javascript 复制代码
function test() {
    console.log(me); // undefined
    if(false) {
        var me = '小杨';
    }
}
test();

即使if条件为false,变量声明依然会被提升!

四、作用域链:变量的"寻亲记"

javascript 复制代码
let name = '全局小杨';

function outer() {
    let name = '外层小杨';
    
    function inner() {
        console.log(name); // '外层小杨'
    }
    inner();
}
outer();

JS会沿着作用域链一层层往上找变量,就像寻亲一样。

五、this指向:最难捉摸的"演员"

this的指向总让人头大,记住几个规则:

  1. 普通函数调用:this指向window(严格模式undefined)
  2. 方法调用:this指向调用对象
  3. new调用:this指向新创建的对象
javascript 复制代码
let obj = {
    me: '小杨',
    say: function() {
        console.log(this.me);
    }
};

obj.say(); // '小杨'
let fn = obj.say;
fn(); // undefined (this指向window)

六、闭包:执行上下文的"遗产"

javascript 复制代码
function createCounter() {
    let count = 0;
    return function() {
        count++;
        console.log(count);
    };
}

let counter = createCounter();
counter(); // 1
counter(); // 2

即使createCounter的执行上下文已经销毁,内部函数依然能访问count变量,这就是闭包的魔力。

七、实战应用:避免常见坑

  1. 避免变量污染
javascript 复制代码
// 错误做法
for(var i=0; i<5; i++) {
    setTimeout(() => {
        console.log(i); // 全是5
    }, 100);
}

// 正确做法
for(let i=0; i<5; i++) {
    setTimeout(() => {
        console.log(i); // 0,1,2,3,4
    }, 100);
}
  1. 合理使用闭包
javascript 复制代码
// 缓存计算结果
function createCache() {
    let cache = {};
    return function(key, value) {
        if(value !== undefined) {
            cache[key] = value;
        }
        return cache[key];
    }
}

八、总结

  • 执行上下文是JS代码执行的环境
  • 变量提升和作用域链是理解JS的关键
  • this指向需要根据调用方式判断
  • 闭包可以让函数"继承"执行上下文的变量

最后留个思考题:

javascript 复制代码
let obj = {
    me: '小杨',
    say: () => {
        console.log(this.me);
    }
};
obj.say(); // 输出什么?为什么?

欢迎在评论区讨论你的答案!下期我会详细讲解箭头函数的this指向问题。

相关推荐
_r0bin_1 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
IT瘾君1 小时前
JavaWeb:前端工程化-Vue
前端·javascript·vue.js
zhang98800001 小时前
JavaScript 核心原理深度解析-不停留于表面的VUE等的使用!
开发语言·javascript·vue.js
potender1 小时前
前端框架Vue
前端·vue.js·前端框架
站在风口的猪11082 小时前
《前端面试题:CSS预处理器(Sass、Less等)》
前端·css·html·less·css3·sass·html5
程序员的世界你不懂2 小时前
(9)-Fiddler抓包-Fiddler如何设置捕获Https会话
前端·https·fiddler
MoFe13 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
去旅行、在路上3 小时前
chrome使用手机调试触屏web
前端·chrome
Aphasia3114 小时前
模式验证库——zod
前端·react.js
lexiangqicheng4 小时前
es6+和css3新增的特性有哪些
前端·es6·css3