如今开始讲做用域链🕺🏼在这篇文章中,我假设您了解执行上下文:尽管如此,我也将很快就此发表一篇文章😃javascript
让咱们看下面的代码:java
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())
复制代码
咱们调用getPersonInfo函数,该函数返回一个包含name,age,city的值的字符串: Sarah is 22 and lives in San Francisco
。可是getPersonInfo函数不包含名为city🤨 的变量。它怎么知道city的?git
首先,为不一样的上下文设置存储空间。咱们有默认的全局上下文
(在浏览器中是window
,在Node中是 global
),以及getPersonInfo的局部上下文
。每一个上下文也都有一个做用域链
。github
对于getPersonInfo来讲,做用域链看起来像这样(看不懂?不用担忧,下面会讲):浏览器
做用域链是对对象的“引用链”,这些对象包含对在该执行上下文中可引用的值(和其余做用域)。(⛓:“嘿,这些都是您能够在此上下文中引用的全部值”。)做用域链是在建立执行上下文时建立的,这意味着它是在运行时建立的!函数
可是,在本文中,我通常不会讨论活动对象
或执行上下文,咱们只关注做用域!在如下示例中,执行上下文中的键/值对表示做用域链对变量的引用。oop
全局执行上下文的做用域链引用了3个变量:name
的值是Lydia,age
的值是21,city
的值是San Francisco。在本地上下文中,咱们引用了2个变量:name
的值是Sarah和age
的值是22。post
当咱们尝试访问getPersonInfo函数中的变量时,引擎首先检查本地做用域链。ui
本地做用域链引用了name和age!name的值为Sarah,age的值为22。可是如今,当它尝试访问city时会发生什么?spa
为了找到city的值,引擎“沿做用域链往下”。这意味着引擎不会轻易放弃:它会努力为您查看是否能够city在本地做用域引用的外部做用域(在本例中为全局对象)中找到变量的值。
在全局上下文中,咱们声明了变量city,它的值为San Francisco
,所以引用了变量city。如今咱们有了变量的值,函数getPersonInfo能够返回字符串Sarah is 22 and lives in San Francisco
🎉
咱们能够顺着做用域链向下,但咱们顺着做用域链向上。(好吧,这可能会使人困惑,由于有些人说的是向上而不是向下,因此我要改写:您可使用外部做用域,但不能进入内部做用域。我想用瀑布形象地表示这一点
甚至更深:
让咱们以这段代码为例。
几乎同样,可是有一个很大的不一样:咱们如今仅在getPersonInfo函数中声明city,而不是在全局范围中声明。咱们没有调用getPersonInfo函数,所以也没有建立本地上下文。然而,咱们试图在全局做用域访问name,age,city。
它抛出ReferenceError!在全局做用域内它找不到一个叫作city的变量,而且没有外部做用域,而且它不能沿着做用域链向上。
这样,您能够利用做用域来“保护”变量或者从新使用变量。
除了全局和局部做用域外,还有一个块做用域
。用let 或 const关键字声明的变量的做用域为最接近的大括号({})。
const age = 21
function checkAge() {
if (age < 21) {
const message = "You cannot drink!"
return message
} else {
const message = "You can drink!"
return message
}
}
复制代码
您能够将范围可视化为:
咱们有一个全局做用域,一个函数做用域和两个块做用域。因为message用大括号括起来,所以咱们可以对变量进行两次声明。
快速回顾:
范围(链)就是这样!关于这一点,还有不少话要说,因此我会在空闲时间添加一些额外的信息。若是您遇到任何困难,请随时提出问题,我很乐意提供帮助!💕
本系列包括6篇文章