我第一次真正理解了作用域链

最近在摸鱼的时候忽然刷到一个面试题,考察的是有关作用域链的,当时就想八股文里应该没有比作用域链更简单的了,后来果然毫无意外的答错了,原来我根本就不了解它,只是以前没有撞枪口上,这下栽了。本文就浅浅记录一下我更正错误的决心

面试题

js 复制代码
function bar() {
    console.log(myName)
}
function foo() {
    var myName = "foo里面"
    bar()
}
var myName = "foo外面"
foo()

看到题目的第一反应,就判断了答案是foo里面,想着bar里面没有myName,然后直接找他的上级foo,答案不就出来了吗,控制台直接打印,GG......

调用栈

首先,要理解作用域链要先理解好js的执行机制,抛开变量提升什么乱七八糟的先不谈,js的执行机制概括来说就是先编译,后执行。我们主要分析的是编译阶段。

一段js代码在执行前,都会编译并创建执行上下文,一般有以下几种情况

  • JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文,而且在整个页面的生存周期内,全局执行上下文只有一份。
  • 当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
  • 当使用 eval 函数的时候,eval 的代码也会被编译,并创建执行上下文。

编译阶段创建好执行上下文,压入调用栈,遵循先进后出的原则

由此,根据代码,可以得到以下调用栈的示意图

let、const关键字定义的变量不存在变量提升,才会被保存在词法环境

按照上面的图,我坚信我自己是对的,肯定是js有毒

outer

经过进一步查资料,发现了它 - outer

其实在每个执行上下文的变量环境中,都包含了一个外部引用,用来指向外部的执行上下文,我们把这个外部引用称为 outer

词法作用域

可是我们不知道outer的指向规则是什么,主观意识就觉得会指向foo的 执行上下文,但其实不然,还和另一个概念有关,它叫做词法作用域

词法作用域就是指作用域是由代码中函数声明位置来决定的,所以词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符

作用域链是由词法作用域决定的

真相

引入新概念,我们可以把上图优化一下

从图中可以看出,barfooouter 都是指向全局上下文的,这也就意味着如果在 bar或者 foo中使用了外部变量,那么 JavaScript 引擎会去全局执行上下文中查找。我们把这个查找的链条就称为作用域链。同时也说明了,词法作用域是代码编译阶段就决定好的,和函数是怎么调用的没有关系。

相关推荐
colicode25 分钟前
安卓Android语音验证码接口API示例代码:Kotlin/Java版App验证开发
android·java·前端·前端框架·kotlin·语音识别
万物得其道者成9 小时前
前端大整数精度丢失:一次踩坑后的实战解决方案(`json-bigint`)
前端·json
鹏北海9 小时前
移动端 H5 响应式字体适配方案完全指南
前端
姜太公钓鲸23310 小时前
ROM就是程序存储器,实际的存储介质是Flash闪存。上述描述中的程序存储器是什么意思?
开发语言·javascript·ecmascript
柳杉11 小时前
使用AI从零打造炫酷医疗数据可视化大屏,源码免费拿!
前端·javascript·数据可视化
凌云拓界11 小时前
前端开发的“平衡木”:在取舍之间找到最优解
前端·性能优化·架构·前端框架·代码规范·设计规范
zhengfei61111 小时前
【XSS payload 】一个经典的XSS payload
前端·xss
简单Janeee12 小时前
[Vue 3 从零到上线]-第四篇:组件化思维——把网页像积木一样拆解
javascript·vue.js·ecmascript
全栈老石13 小时前
手写一个无限画布 #1:坐标系的谎言
前端·canvas
XW010599913 小时前
4-11判断素数
前端·python·算法·素数