作者第一次听到词法作用域这个词, 还是在一篇提及闭包的文章当中。当时也就过了下眼睛,想着吧, 这玩意了解下就行,和我工作开发也没啥关系。但是随着作者的深入了解,发现其实我们工作中的很多代码实现, 还真就离不开它,一起来看看吧。
词法作用域
先看看百度百科咋说
词法作用域,也叫静态作用域,它的作用域是指在词法分析阶段就确定了,不会改变。
脱离专业术语,js中的词法作用域,就是一个作用域(例如函数作用域),可以访问到的 任意其他作用域,这个其他作用域就是该函数作用域的词法作用域。 简单吧!我举例说明:
下文实验环境: 使用vue 脚手架搭建的一个空项目( vite + ts + vue3)
vue3
<script setup lang="ts">
const a = 1
function funcOne() {
const b = 2
return function funcTwo() {
return a + b
}
}
console.log(funcOne()()) // 3
</script>
在上述代码中
对于函数 funcOne:该函数可以访问script标签中定义的任意成员。那这个script标签构建出的作用域就是 funcOne 的词法作用域
对于函数 funcTwo:该函数除了可以访问script标签中的成员, 还可以访问funcOne函数中的成员。那么就可以说 script标签构建出的作用域 和 funcOne的函数作用域 是funcTwo的词法作用域
可能有很多读者对上述的案例解释觉得略显牵强。这不就是内层作用域可以引用外层作用域中的变量吗? 这外层作用域就是词法作用域啦? 答案是:是的!
之所以大家会有这种牵强的感觉,是因为作者上述对词法作用域的解释并不完善。真正的词法作用域还应该满足一个条件: 内层作用域可以引用外层作用域中的变量, 这种引用关系在函数定义的时候就确认了。
可能有小伙伴就要吐槽了,这种引用关系啥时候确认和我有啥关系? 哎, 你还别说, 这关系还真不小。 举个最常见例子:
上述代码很简单。 左侧文件utils.ts中导出了一个方法funcThree 在右侧 vue组件中使用。调皮的问下,vue文件中调用的funcThree 方法执行的结果是多少咧? 答案是: 1。为啥不是2? 这就是用到的了上述特性: 这种引用关系在函数定义的时候就确认了。 也正是因为这种的特性,所以:词法作用域,也叫静态作用域。
试想, 如果这个特性不存在话会怎么样, 上述的答案可能是2。这问题大吗?emm, 好像还不是很大。。。那如果utils文件中的变量a,改成axios,或是其他第三方工具呢?这问题就大了去了。因为这将导致整个es6中模块的概念失去意义。上述只是举了一个常见的例子,其实啊,整个js语言都是建立在词法作用域之上的,可以说没有词法作用域, 就没有js。
有关词法作用域其实可以牵扯出很多东西,像是与之相反的动态作用域、js编译原理、分词啥的,在这就不和大家细说了(咳咳, 主要是作者也不太会~)。大家只需要了解啥是词法作用域即可,我带大家再总结一波:
词法作用域:一个作用域(例如函数作用域),可以访问到的任意其他作用域,这种引用关系在函数定义的时候就确认了。那这个其他作用域就是该函数作用域的词法作用域。
以上就是今天的全部内容啦,谢谢各位看官老爷的观看。不好的地方,还请包涵。不对的地方,还请指正