我所知道的Javascript(上)-作用域

120 阅读3分钟

前言

最近在做笔试和面试的过程中,我意识到自己对JS似乎不是很理解,大部分是为了应付面试的八股文记忆,然而对于面试官进一步的提问,往往哑口无言,为了解决这一问题,读了同学推荐的书:《你所不知道的Javascript》,此篇文章仅代表个人对这本书知识的理解与总结,如果能帮到没时间看书的前端爱好者都一举两得啦~ (欢迎指正)

作用域

什么是作用域

我曾经认为,作用域就是代码中{}之内的部分,毕竟函数作用域与块作用域都包裹在{}之内,然而这是比较浅显的错误理解,毕竟全局作用域便没有{},并且我们应该把作用域想象成一个能够记忆变量的范围,超脱了这个范围便找不到这些变量,下面是简单的演示

批注 2024-07-19 091727.png

词法作用域

什么是词法作用域?我们小白不太关心,只要知道JS用的是词法作用域就好了,关于词法作用域的理解,书中讲的特别好,这里挪用书中的理解:

image.png 我们能可以看到图中类似有三层气泡,词法作用域的变量获取规则是从内到外就近获取,它会首先从自己的作用域去查找,未然则开始去外层查找,就是这么一个简单的过程,因此也特别好理解书中所说的:词法作用域是由你在写代码时将变量和块作用域写在哪里决定的

函数作用域与块作用域

我曾经所过函数作用域即函数部分{}之内的范围,块作用域则是if、for等的{}之内的范围,这么讲很好理解,也不算什么错误,下面则是我想分享的几点细则: 首先函数作用域与块作用域属于词法作用域,因此它们获取变量的原则与词法作用域相同即从内到外就近获取,这一点是相当基础的。 其次,我们上面提到的从内到外就近的获取这一点上需要注意的是,内应该是当前作用域而不是最内层的作用域,不然可能无法理解一些结果,例如下面的代码:

image.png

再者,我们看到上面代码中,全局与foo中各自有一个a的声明和赋值,并且它们的赋值不会覆盖,因为它们的领地不同。你可以想象,foo中的a无论做了什么,他只能在foo中豪横,也就是说无论他在foo中做了什么赋值,到了外层都会被JS所忽略。这里补充一点,如果你曾经和我一样错误的理解var的变量提升,错误的认为它能够将var a = 3提升到代码前头从而覆盖2,那么这个理解十分糟糕,因为var的变量提升只能够提升声明也就是var a的部分并且在已经声明的情况下会被忽略,并且理解var的提升应把它当作var的特性而不是特点,也可以说是var的漏洞 最后,块作用域是在es6之后和const、let一起出现的,这之前JS主要依赖函数作用域,这导致函数内的变量使用相当麻烦,需要十分注意变量的命名以避免全局命名空间的污染和变量覆盖问题,块作用域与const、let的出现使得JS诞生了局部变量,它们也不存在提升的问题,经典的代码演示局部变量出现的必要性:

image.png

image.png

i的修改并不是该方法的本意,只是在该作用于下,var申明的变量i共用一块内存,在for循环中的修改覆盖了外层的i,块作用域和局部变量就是为了解决这一情况:

image.png

image.png