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

【动画演示】:JS 作用域链不在话下 #174

Open
husky-dot opened this issue Dec 30, 2019 · 0 comments
Open

【动画演示】:JS 作用域链不在话下 #174

husky-dot opened this issue Dec 30, 2019 · 0 comments

Comments

@husky-dot
Copy link
Owner

husky-dot commented Dec 30, 2019

作者:Lydia Hallie
译者:前端小智
来源:dev

本篇我们来看看啥是作用域以及作用域链,首先,来看看下面的代码:

const name = "Lydia"
const age = 21
const city = "San Francisco"


function getPersonInfo() {
  const name = "Sarah"
  const age = 22

  return `${name} is ${age} and lives in ${city}`
}

console.log(getPersonInfo())
// Sarah is 22 and lives in San Francisco

我们调用getPersonInfo函数,它返回一个包含姓名、年龄和城市变量值的字符串:Sarah is 22 and lives in San Francisco。但是,getPersonInfo函数中不包含变量 city,它是怎么取到 city 的值?

首先,JS 引擎为不同的上下文设置内存空间。我们有默认的全局上下文(浏览器中的window、Node 中的global ),以及已经调用的getPersonInfo函数的本地上下文,每个上下文还有一个作用域链

对于getPersonInfo函数,作用域链看起来是这样的:

作用域链基本上是对对象的“引用链”,其中包含对在执行上下文中可引用的值(和其他作用域)的引用。作用域是在创建执行上下文时创建的,这说明它是在运行时创建的。

在本文中,不会讨论激活对象或执行上下文,我们只关注作用域。 在以下示例中,执行上下文中的键/值对表示使作用域链对变量的引用。

**全局执行上下文(GLOBAL EXECUTION CONTEXT)的作用域链引用了3个变量:值为Lydianame、值为21age和值为San Franciscocity。在本地执行上下文(LOCAL EXECUTION CONTEXT)**中,我们引用了两个变量:name值为Sarah, age值为22

当我们试图访问getPersonInfo函数中的变量时,JS引擎首先检查局部作用域链。

本地作用域链有一个nameage的引用!name的值是Sarah, age的值是22。但是现在,当它试图访问city变量时会发生什么?

为了找到变量city的值,JS 引擎沿着作用域链向上查找,直到在外部作用域内为找到了一个city的值,本地作用域有一个引用,在本例中是全局对象

在全局上下文中,我们用San Francisco的值声明了变量city,因此有一个对变量city的引用。现在我们有了变量的值,函数getPersonInfo可以返回字符串Sarah is 22 and lives in San Francisco

我们可以沿着作用域链向下走,但是我们不能沿着作用链向上走,这可能会让人困惑,因为我们大都会说“向上”而不是“向下”,所以换一种说法:你可以进入外部作用域,但不能进入内部作用域,可以把它想象成瀑布模型:

更深的嵌套:

以这段代码为例:

这个跟上个例子代码几乎是一样的,但是有一个很大的区别:我们现在只在getPersonInfo函数中声明city,而不在全局作用域中。这里也没有调用getPersonInfo函数,所以也没有创建本地上下文。然而,我们试图在全局上下文中访问nameagecity的值。

这里分抛出一个ReferenceError异常,因为 JS 在全局范围内找不到一个名为city的变量的引用,因为已处于顶部作用域,也没法向上的作用域查找了。

通过这种方式,我们可以将作用域用作“保护”变量并重新使用变量名的方法。

除了全局作用域和局部作用域之外,还有一个块作用域。使用letconst关键字声明的变量的作用域就是块作用域。

const age = 21

function checkAge() {
  if (age < 21) {
    const message = "You cannot drink!"
    return message
  } else {
    const message = "You can drink!"
    return message
  }
} 

可以将上面的作用域可视化为:

这里有一个全局作用域、一个函数作用域和两个块作用域。我们可以两次声明变量message ,因为message 变量处在不同的作用域中。

快速回顾:

  • 可以将“作用域链”看作是在当前上下文中访问的值的引用链。
  • 作用域还可以重用在该该作用域链上定义的变量名,因为它会沿着作用域链向上查找。

原文:https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug


交流

干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。

https://github.com/qq449245884/xiaozhi

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,即可看到福利,你懂的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant