软件教程 2025年08月6日
0 收藏 0 点赞 447 浏览 1920 个字
摘要 :

文章目录 调用栈 作用域链 闭包 总结 本文重点讲解什么是调用栈、作用域链和闭包?我们来一起学习下! 调用栈 调用栈是用来管理函数调用关系的一种数据结构。当一个函……




本文重点讲解什么是调用栈、作用域链和闭包?我们来一起学习下!

调用栈

调用栈是用来管理函数调用关系的一种数据结构。当一个函数被调用时,会将其添加到调用栈的顶部,然后执行该函数的代码。当函数执行完毕后,会将其从调用栈中移除。

调用栈的操作遵循”先进后出”(LIFO)的原则,即最后调用的函数先执行完毕,然后才能继续执行前一个调用的函数。通过调用栈,我们可以追踪函数的执行顺序,以及在函数执行过程中的上下文信息。什么是调用栈、作用域链和闭包?

在拿到代码的那一刻,调用栈就已经生成,然后生成全局执行上下文,这里面会生成变量环境和词法环境(let 和const声明的变量会在词法环境中)。预编译找到a,值为undefined;add,值为function。开始执行,2赋值给了a,调用函数add。形成add的执行上下文,预编译开始编译函数内的内容,发现b,值为undefined。开始执行,10赋值给了b,return a = b,但是在自己的作用域内并不能找到a(按照 词法作用域->变量环境去查找),于是又去到全局中找到a=2。所以返回12。

作用域链

作用域链是通过词法环境来确定某一作用域的外层作用域,并形成一个查找变量的链状关系。在JavaScript中,每个函数都有自己的作用域,当在函数中访问一个变量时,会先从当前作用域开始查找,如果找不到,则会向外层作用域继续查找,直到找到变量或者到达全局作用域。

作用域链的形成是在函数定义阶段确定的,而不是在函数执行阶段。这意味着在函数定义时,就已经确定了函数在哪个作用域中执行,以及它可以访问哪些变量。

我们知道,栈是有大小的,所以为了防止作用栈被撑爆,当一条语句被执行完毕时,它在调用栈内形成的作用域(也就是执行上下文)将会被清除。什么是调用栈、作用域链和闭包?

 

如上图:全局中有函数bar,foo,变量myName。因为调用了函数foo所以生成foo的执行上下文:有变量myName。执行bar的调用,bar的作用域中并没有东西,执行打印语句,输出myName的值,自己的作用域中没有,来到全局中找到myName=万总(函数声明在了哪里,outer的值就记在哪里)。

这里的outer是什么?其实是js的v8引擎自带的一个属性,它决定了函数在哪个作用域中执行,以及它可以访问哪些变量。 执行完打印语句,第7行执行完毕,bar的作用域出栈,紧接着foo也执行完毕,foo出栈,全局执行完毕,出栈。

闭包

闭包是JavaScript中一个重要的概念,它是由词法作用域规则支持的。当一个内部函数引用了外部函数中的变量,并且这个内部函数被外部函数返回时,就形成了闭包。什么是调用栈、作用域链和闭包?

如图:全局中有test和res,执行,第12调用了函数test。来到test的作用域中,词法环境中有count,变量环境中有help。开始执行,把0赋值给count,return help,得到1。可以知道第12行已经执行完毕了,所以test作用域该出栈了,但我们注意到,函数test最后是return了函数help的,可以理解为return把它带离了函数test。如果就这么销毁他,我们可以认为这是有问题的。所以在test出栈时,会形成一个闭包,用来保存被带离的值。即当执行13行时,得到help返回的值为1,存在了闭包中,继续执行14行,不再是count=0 -> ++count,help返回值为1,而是在闭包中找到count=1,++count,help返回值为2,同理15行返回3。

闭包的特点是,即使外部函数已经执行完毕,但是内部函数仍然可以访问外部函数中的变量。这是因为闭包会将外部函数中被引用的变量保存在内存中,以供内部函数后续使用。

闭包的优点之一是实现了变量的私有化,即外部无法直接访问内部函数引用的变量。这可以提供更好的封装性和安全性。

然而,闭包也可能导致内存泄漏的问题。当一个函数返回一个闭包时,如果这个闭包持有大量的外部变量引用,而且不再被使用,那么这些变量将无法被垃圾回收机制释放,从而造成内存泄漏。

为避免闭包导致的内存泄漏问题,我们应该在不需要使用闭包时手动解除对外部变量的引用,或者及时释放闭包所占用的内存空间。

总结

总结: 本文详细介绍了JavaScript中的调用栈、作用域链和闭包。调用栈用于管理函数调用关系,作用域链通过词法环境确定了变量的查找顺序,而闭包则是形成了内部函数对外部函数变量的引用。闭包具有实现私有化变量的优点,但也存在内存泄漏的风险,需要注意及时解除变量引用或释放内存空间。了解和掌握这些概念对于理解JavaScript中的函数执行和变量作用域非常重要。

闭包虽好,可不要贪多哦,毕竟栈是有大小的。、

以上就是什么是调用栈、作用域链和闭包,你学会了吗?

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6379.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号