图解javascript作用域

云儿
• 阅读 739

图解javascript作用域

本文原文地址

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

作用域访问规则

let count = 0;

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

func();

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

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

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

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

如下图所示:

图解javascript作用域

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

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

作用域创建规则

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

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

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

let count = 0;

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

func('func');

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

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

如下图所示:

图解javascript作用域

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

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

总结

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

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

参考

MDN文档

《你不知道的Javascript上卷》

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Symbol卢 Symbol卢
4年前
秒懂js作用域与作用域链
JavaScript中有一个被称为作用域(Scope)的特性。虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,本文我会尽我所能用最简单的方式来解释作用域和作用域链,希望大家有所收获!好了下面开始我们的正文作用域常见的解释(什么是作用域)1.一段程序代码中所用到的名字并不总是有效,而限定它的可用性的范围就是这个名字的作用域;2.作用域规定了
Karen110 Karen110
3年前
一篇文章带你了解JavaScript作用域
在JavaScript中,对象和函数也是变量。在JavaScript中,作用域是你可以访问的变量、对象和函数的集合。JavaScript有函数作用域:这个作用域在函数内变化。一、本地JavaScript变量一个变量声明在JavaScript函数内部,成为函数的局部变量。局部变量有局部作用域:它们只能在函数中访问。JS://codeherecann
菜园前端 菜园前端
2年前
为你解惑JS作用域和作用域链知识
原文链接:变量作用域一个变量的作用域(scope)是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都是可以访问的。然而在函数内声明的变量只能在函数体内访问,它们是局部变量,作用域是局部性的。函数参数也是局部变
Stella981 Stella981
3年前
ES6 新特性之 let, const : JavaScript在变量方面的改进。
let:块级作用域我们知道,JavaScript是没有块级作用域的,如果在块内使用var声明一个变量,它在代码块外面仍旧是可见的:if(true){varfoo3;}console.log(foo);//3for(vari0
Stella981 Stella981
3年前
JavaScript 作用域
在学习js的过程对闭包什么的,理解不好,偶然搜到这篇文章。豁然开朗,随翻译。Javacript中有一系列作用域的概念。对于新的JS的开发人员无法理解这些概念,甚至一些经验丰富的开发者也未必能。这篇文章主要目的帮助理解JavaScript中的一些概念如:scope,closure,this,namespace,functionscope,
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
JavaScript作用域
一、JavaScript中无块级作用域在Java或C中存在块级作用域,即:大括号也是一个作用域。!(https://oscimg.oschina.net/oscnet/ea3e9460a4d20056c59315db47e2a0cbc2b.jpg)!(https://oscimg.oschina.ne