Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

图解javascript作用域 #39

Open
HerryLo opened this issue Feb 20, 2023 · 0 comments
Open

图解javascript作用域 #39

HerryLo opened this issue Feb 20, 2023 · 0 comments
Assignees
Labels
Blog 文章

Comments

@HerryLo
Copy link
Member

HerryLo commented Feb 20, 2023

图解javascript作用域

本文原文地址

此文章是回答知乎问题总结而来

作用域访问规则

let count = 0;

function func() {
  console.log(count);
}

func();

下面我们来看看变量count是如何被打印出来:

1. `func`函数调用,`console.log`打印`count`变量,查找当前函数作用域,是否存在变量`count`;
2. 不存在继续向上查找,查找模块作用域,发现`count`变量存在,并且打印出变量的值。

如果模块作用域依然不存在count变量?

会继续向上查找,查找全局作用域是否存在count变量,如果依然不存在,提示undefined

如下图所示:

通过上面的示例代码,我们可以知道一个规则,作用域访问顺序:函数作用域 ——> 模块作用域 ——> 全局作用域

提示:作用域访问的方向是不可逆只有由里向外访问,先函数,再模块,最后全局;

作用域创建规则

JavaScript中的作用域是词法作用域(相对于动态作用域)。

什么叫词法作用域?顾名思义,词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪来决定的。

无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定,这就是JavaScript的词法作用域。(除非你使用 with 或者 eval 欺骗它)
我们来看下面的例子:

let count = 0;

function func(name) {
  console.log(count, name);
}

func('func');

代码执行,作用域创建顺序:

1. 优先创建全局作用域,如全局window对象,或者挂载在全局的函数或属性;
2. 之后模块作用域被创建,`count`变量会挂载在模块作用域,`func`函数也是挂载在模块作用域;
3. 最后才是函数作用域,此时全局作用域和模块作用域已创建生成,如果它需要使用外部的存在的变量或方法,只需向上查找即可;

如下图所示:

上图中作用域创建是至上而下,我省略了表示递进关系的线条。我们来归纳一下,作用域创建顺序是:全局作用域 ——> 模块作用域 ——> 函数作用域

在调用完成之后,作用域也会相应释放。如果是存在闭包,作用域链就会被保存,可以看看:闭包装逼失败(闭包使用) - 掘金

总结

  • 作用域访问顺序:函数作用域 ——> 模块作用域 ——> 全局作用域
  • 作用域访问的方向是不可逆只有由里向外访问
  • 作用域创建顺序是:全局作用域 ——> 模块作用域 ——> 函数作用域

以上内容希望可以帮助到你,你的点赞、收藏是我更新的动力!!

参考

MDN文档

《你不知道的Javascript上卷》

冴羽 · JavaScript深入之执行上下文

@HerryLo HerryLo self-assigned this Feb 20, 2023
@HerryLo HerryLo added the Blog 文章 label Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blog 文章
Projects
None yet
Development

No branches or pull requests

1 participant