zoukankan      html  css  js  c++  java
  • 【动画演示】:JS 作用域链不在话下

    作者:Lydia Hallie
    译者:前端小智
    来源:dev
    点赞再看,养成习惯

    本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。


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

    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函数,作用域链看起来是这样的:

    clipboard.png

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

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

    clipboard.png

    全局执行上下文(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

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

    clipboard.png

    更深的嵌套:

    clipboard.png

    以这段代码为例:

    clipboard.png

    这个跟上个例子代码几乎是一样的,但是有一个很大的区别:我们现在只在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
      }
    } 
    

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

    clipboard.png

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

    快速回顾:

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

    原文:https://dev.to/lydiahallie/ja...

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


    交流

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

    https://github.com/qq44924588...

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

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

    clipboard.png

  • 相关阅读:
    IIS7.5应用程序池集成模式和经典模式的区别介绍(转)
    (转)Extjs4 展示图片与图片的更新
    webservices发布后远程无法调试的解决方法
    .Net通过OleDb方式读取Excel
    1000个JQuery插件(转载)
    2006年中科大计算机考研复试机试题
    2. 最好使用C++转型操作符
    16. 谨记8020法则
    英语阅读理解中表示作者态度的词汇汇总
    5. 对定制的“类型转换函数”保持警觉
  • 原文地址:https://www.cnblogs.com/dearroy/p/12200810.html
Copyright © 2011-2022 走看看