JS的作用域和作用域链
作用域
定义
作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。
⚠️:作用域是由代码中函数声明的位置来决定的,跟在哪里调用无关
用途
作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
类别
- 全局作用域
- 最外层函数 和在最外层函数外面定义的变量拥有全局作用域
- 所有末定义直接赋值的变量自动声明为拥有全局作用域
- 所有 window 对象的属性拥有全局作用域
- 函数作用域
在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。函数执行结束之后,函数内部定义的变量会被销毁。
- 块级作用域(ES6新增)
ES6 引入了 let 和 const 关键字,从而使 JavaScript 也能像其他语言一样拥有了块级作用域。
作用域链
定义
简单来说就是由作用域组成的链条。例如在函数里面有个a变量,函数内部不存在,则会找他的父级作用域,直到找到或者在全局作用域还没找到则放弃。(在ES5之后是通过变量环境里的outer即外部环境来实现的)
用途
通过作用域来找变量(查找变量的机制)。注意⚠️:内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境的任何变量和函数。
作用域与执行上下文
许多开发人员经常混淆作用域和执行上下文的概念,误认为它们是相同的概念,但事实并非如此。
我们知道 JavaScript 属于解释型语言,JavaScript 的执行分为:解释和执行两个阶段,这两个阶段所做的事并不一样。
解释阶段
- 词法分析
- 语法分析
- 作用域规则确定
执行阶段
- 创建执行上下文
- 执行函数代码
- 垃圾回收
JavaScript 解释阶段便会确定作用域规则,因此作用域在函数定义时就已经确定了,而不是在函数调用时确定,但是执行上下文是函数执行之前创建的。执行上下文最明显的就是 this 的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。
其实大家看下作用域和执行上下文各自的职责,你会发现他们几乎是没有啥交集的。那么为啥通常两者会被同时提到呢?因为在一个函数被执行时,创建的执行上下文对象除了保存了些代码执行的信息,还会把当前的作用域保存在执行上下文中。所以它们的关系只是存储关系。
参考
https://www.cnblogs.com/fundebug/p/10535230.html
极客时间浏览器原理与实践