没有合适的资源?快使用搜索试试~ 我知道了~
10-作用域链和闭包:代码中出现相同的变量,JavaScript引擎是如何选择的?_For_vip_user_0011
需积分: 0 0 下载量 187 浏览量
2022-08-04
13:27:21
上传
评论
收藏 1.33MB PDF 举报
温馨提示
试读
12页
在上篇章中我们讲到了什么是作域,以及ES6是如何通过变量环境和词法环境来同时持变量提升和块级作域,在最后我们也提到了如何通过词法环境和变量环境来查找变量,这其中
资源详情
资源评论
资源推荐
10-作⽤域链和闭包:代码中出现相同的变量,JavaScript引擎是如何选择的?10-作⽤域链和闭包:代码中出现相同的变量,JavaScript引擎是如何选择的?
在上⼀篇⽂章中我们讲到了什么是作⽤域,以及ES6是如何通过变量环境和词法环境来同时⽀持变量提升和
块级作⽤域,在最后我们也提到了如何通过词法环境和变量环境来查找变量,这其中就涉及到作⽤域链作⽤域链的概
念。
理解作⽤域链是理解闭包的基础,⽽闭包在JavaScript中⼏乎⽆处不在,同时作⽤域和作⽤域链还是所有编
程语⾔的基础。所以,如果你想学透⼀⻔语⾔,作⽤域和作⽤域链⼀定是绕不开的。
那今天我们就来聊聊什么是作⽤域链什么是作⽤域链,并通过作⽤域链再来讲讲什么是闭包什么是闭包。
⾸先我们来看下⾯这段代码:
你觉得这段代码中的bar函数和foo函数打印出来的内容是什么?这就要分析下这两段代码的执⾏流程。
通过前⾯⼏篇⽂章的学习,想必你已经知道了如何通过执⾏上下⽂来分析代码的执⾏流程了。那么当这段代
码执⾏到bar函数内部时,其调⽤栈的状态图如下所⽰:
执⾏bar函数时的调⽤栈
functionbar(){
console.log(myName)
}
functionfoo(){
varmyName="极客邦"
bar()
}
varmyName="极客时间"
foo()
从图中可以看出,全局执⾏上下⽂和foo函数的执⾏上下⽂中都包含变量myName,那bar函数⾥⾯
myName的值到底该选择哪个呢?
也许你的第⼀反应是按照调⽤栈的顺序来查找变量,查找⽅式如下:
1. 先查找栈顶是否存在myName变量,但是这⾥没有,所以接着往下查找foo函数中的变量。
2. 在foo函数中查找到了myName变量,这时候就使⽤foo函数中的myName。
如果按照这种⽅式来查找变量,那么最终执⾏bar函数打印出来的结果就应该是“极客邦”。但实际情况并
⾮如此,如果你试着执⾏上述代码,你会发现打印出来的结果是“极客时间”。为什么会是这种情况呢?要
解释清楚这个问题,那么你就需要先搞清楚作⽤域链了。
作⽤域链作⽤域链
关于作⽤域链,很多⼈会感觉费解,但如果你理解了调⽤栈、执⾏上下⽂、词法环境、变量环境等概念,那
么你理解起来作⽤域链也会很容易。所以很是建议你结合前⼏篇⽂章将上⾯那⼏个概念学习透彻。
其实在每个执⾏上下⽂的变量环境中,都包含了⼀个外部引⽤,⽤来指向外部的执⾏上下⽂,我们把这个外
部引⽤称为outerouter。
当⼀段代码使⽤了⼀个变量时,JavaScript引擎⾸先会在“当前的执⾏上下⽂”中查找该变量,
⽐如上⾯那段代码在查找myName变量时,如果在当前的变量环境中没有查找到,那么JavaScript引擎会继
续在outer所指向的执⾏上下⽂中查找。为了直观理解,你可以看下⾯这张图:
带有外部引⽤的调⽤栈⽰意图
从图中可以看出,bar函数和foo函数的outer都是指向全局上下⽂的,这也就意味着如果在bar函数或者foo
函数中使⽤了外部变量,那么JavaScript引擎会去全局执⾏上下⽂中查找。我们把这个查找的链条就称为作作
⽤域链⽤域链。
现在你知道变量是通过作⽤域链来查找的了,不过还有⼀个疑问没有解开,foo函数调⽤的bar函数,那为什
么bar函数的外部引⽤是全局执⾏上下⽂,⽽不是foo函数的执⾏上下⽂?
要回答这个问题,你还需要知道什么是词法作⽤域词法作⽤域。这是因为在JavaScript执⾏过程中,其作⽤域链是由词
法作⽤域决定的。
词法作⽤域词法作⽤域
词法作⽤域就是指作⽤域是由代码中函数声明的位置来决定的,所以词法作⽤域是静态的作⽤域,通过它就词法作⽤域就是指作⽤域是由代码中函数声明的位置来决定的,所以词法作⽤域是静态的作⽤域,通过它就
能够预测代码在执⾏过程中如何查找标识符。能够预测代码在执⾏过程中如何查找标识符。
这么讲可能不太好理解,你可以看下⾯这张图:
词法作⽤域
从图中可以看出,词法作⽤域就是根据代码的位置来决定的,其中main函数包含了bar函数,bar函数中包
含了foo函数,因为JavaScript作⽤域链是由词法作⽤域决定的,所以整个词法作⽤域链的顺序是:foo函数
作⽤域—>bar函数作⽤域—>main函数作⽤域—>全局作⽤域。
了解了词法作⽤域以及JavaScript中的作⽤域链,我们再回过头来看看上⾯的那个问题:在开头那段代码
中,foo函数调⽤了bar函数,那为什么bar函数的外部引⽤是全局执⾏上下⽂,⽽不是foo函数的执⾏上下
剩余11页未读,继续阅读
KerstinTongxi
- 粉丝: 21
- 资源: 277
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0