从作用域到作用域链,思维脑图+代码示例让知识点一目了然!系列(三)

从作用域到作用域链,思维脑图+代码示例让知识点一目了然!系列(三)作用域本篇主要总结了作用域的定义 作用域和作用域链的规则 全局变量和局部变量的关系 利用思维导图代替纯文字描述 提高收获 加油

作用域

JavaScript基础提升合集

?包含this、call、原型链、作用域等基础经典知识点
☕️每周一篇,打好基础,爬升不累
?最全知识点解析,易懂的代码示例收藏方便阅读
?完整版在线阅读,猛戳这里~










目录

前言

在这里插入图片描述

JavaScript内功系列:

  1. this指向详解,思维脑图与代码的结合,让你一篇搞懂this、call、apply。系列(一)
  2. 从原型到原型链,修炼JavaScript内功这篇文章真的不能错过!系列(二)
  3. 本文

一、作用域的定义

一张导图概括本节内容

在这里插入图片描述

注意:除了作用域,在此送大家2020最新企业级 Vue3.0/Js/ES6/TS/React/Node等实战视频教程,点击此处免费获取,小白勿进哦



1.1 常见的解释

  1. 一段程序代码中所用到的名字并不总是有效,而限定它的可用性的范围就是这个名字的作用域;
  2. 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限;
  3. 通俗的讲作用域就是一套规则,用于确定在何处以及如何查找某个变量的规则
function func(){ 
    var a = 100; console.log(a); // 100 } console.log(a) // a is not defined a变量并不是任何地方都可以被找到的 

1.2 JavaScript中作用域工作模型

JavaScript 采用是词法作用域(lexical scoping),也就是静态作用域:

  • 函数的作用域在函数定义的时候就决定了

与之对应的还有一个动态作用域:

  • 函数的作用域是在函数调用的时候才决定的;

1.3 全局变量和局部变量

根据定义变量的方式又可以分为:

局部变量:只能在函数中访问,该函数外不可访问;

  • 定义在函数中的变量
function fn(){ 
    var name = '余光'; console.log(name); } console.log(name); // ? fn(); // ? 

全局:任何地方都能访问到的对象拥有全局作用域。

  • 函数外定义的变量
  • 所有末定义直接赋值的变量自动声明为拥有全局作用域
var a = 100; console.log('a1-',a); function fn(){ 
    a = 1000; console.log('a2-',a); } console.log('a3-',a); fn(); console.log('a4-',a); 

注意:在ES6之后又提出了块级作用域,它们之间的区别我们之后再来讨论。

在这里插入图片描述

二、理解作用域

根据第一节的描述,我们一一验证一下

2.1 理解词法作用域

var value = 1; function foo() { 
    console.log(value); } function bar() { 
    var value = 2; foo(); } bar(); 

我们结合定义去分析:

  • 执行bar函数,函数内部形成了局部作用域;
  • 声明value变量,并赋值2
  • 执行foo函数,函数foo的作用域内没有value这个变量,它会向外查找
  • 根据词法作用域的规则,函数定义时,foo的外部作用域为全局作用域
  • 打印结果是1

如果是动态作用域的话:结果就是2,不知道你是否想明白了?

2.2 全局变量

var str = '全局变量'; function func(){ 
    console.log(str+1); function childFn(){ 
    console.log(str+2); function fn(){ 
    console.log(str+3); }; fn(); }; childFn(); } func(); // 全局变量1 // 全局变量2 // 全局变量3 

再来分析下面的代码:

var a = 100; function fn(){ 
    a = 1000; console.log('a1-',a); } console.log('a2-',a); fn(); console.log('a3-',a); // a2- 100 // 在当前作用域下查找变量a => 100 // a1- 1000 // 函数执行时,全局变量a已经被重新赋值 // a3- 1000 // 全局变量a => 1000 

2.3 局部作用域

局部作用域一般只在固定的代码片段内可访问到,最常见的就是以函数为单位的:

function fn(){ 
    var name="余光"; function childFn(){ 
    console.log(name); } childFn(); // 余光 } console.log(name); // name is not defined 

三、作用域链

3.1 当查找变量的时候都发生了什么?

  • 会先从当前上下文的变量对象中查找;
  • 如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找;
  • 一直找到全局上下文的变量对象,也就是全局对象;
  • 作用域链的顶端就是全局对象;

这样由多个执行上下文的变量对象构成的链表就叫做作用域链,从某种意义上很类似原型和原型链。

3.2 作用域链和原型继承查找时的区别:

  • 查找一个普通对象的属性,但是在当前对象和其原型中都找不到时,会返回undefined
  • 查找的属性在作用域链中不存在的话就会抛出ReferenceError

3.3 作用域嵌套

既然每一个函数就可以形成一个作用域(词法作用域 || 块级作用域),那么当然也会存在多个作用域嵌套的情况,他们遵循这样的查询规则:

  • 内部作用域有权访问外部作用域;
  • 外部作用域无法访问内部作用域;(真是是这样吗?)
  • 兄弟作用域不可互相访问;

在《你不知道的Js》中,希望读者可以将作用域的嵌套和作用域链想象成这样:

在这里插入图片描述

四、思考与总结

4.1 总结

在这里插入图片描述

4.2 思考

最后,让我们看一个《JavaScript权威指南》中的两段代码:

var scope = "global scope"; function checkscope1(){ 
    var scope = "local scope"; function f(){ 
    return scope; } return f(); // 注意 } checkscope1(); var scope = "global scope"; function checkscope2(){ 
    var scope = "local scope"; function f(){ 
    return scope; } return f; } checkscope2()(); 

两段代码的结果都是”local scope”,书中的回答是:JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。

但是它们内部经历的事情是一样的吗?

参考

  • 《你不知道的JavaScript》
  • JavaScript深入之词法作用域和动态作用域

写在最后

JavaScript内功基础部分已经总结到第三篇了,本系列大约会有15篇文章,都是我们在面试最高频的,但工作中常常被忽略的。

热门开源-欢迎star支持

  • 前端进阶
  • 高频经典手撕代码实现
  • 剑指Offer题解
  • LeetCode题解

关于我

  • 花名:余光
  • Writing Vue and JavaScript
  • Working at GaoDing Design
  • A console log tester

从作用域到作用域链,思维脑图+代码示例让知识点一目了然!系列(三)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/207855.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午12:56
下一篇 2026年3月19日 下午12:57


相关推荐

  • ipconfig配置ip地址(为什么输入ipconfig没有用)

     IP可以分为PublicIP和PrivateIP,出现这种规划的原因在于IPv4所能表示的IP太少而电脑太多以至于不够用,然而只有PublicIP才能直接连接上网络,所以对于那些公司,学校,政府机构等场所,就可以集中使用私有的IP进行管理,而大家可以共用一个IP去连接上公网,这样,就省下了许多宝贵的PublicIP。你有没有发现,你每次使用ipconfig查到的地址,要么就是172….

    2022年4月15日
    85
  • OpenClaw云端部署教程[代码]

    OpenClaw云端部署教程[代码]

    2026年3月17日
    2
  • spss数据分析聚类分析_SPSS聚类分析

    spss数据分析聚类分析_SPSS聚类分析SPSS之聚类分析(图文+数据集)聚类分析简介按照个体(记录)的特征将它们分类,使同一类别内的个体具有尽可能高的同质性,而类别之间则具有尽可能高的异质性。为了得到比较合理的分类,首先要采用适当的指标来定量地描述研究对象之间的联系的紧密程度。假定研究对象均用所谓的“点”来表示。在聚类分析中,一般的规则是将“距离”较小的点归为同一类,将“距离”较大的点归为不…

    2022年10月17日
    3
  • linux生成license,License生成秘钥

    linux生成license,License生成秘钥一License简介开发的软件产品在交付使用的时候,往往会授权一段时间的试用期,这个时候license就派上用场了。不同于在代码中直接加上时间约束,需要重新授权的时候使用license可以避免修改源码,改动部署,授权方直接生成一个新的license发送给使用方替换掉原来的license文件即可。下面将讲述使用truelicense来实现license的生成和使用。Truelicense是一个开…

    2022年7月26日
    12
  • linux用命令dpkg,Linux中的dpkg命令介绍

    linux用命令dpkg,Linux中的dpkg命令介绍导读dpkg是一个安装、构建、删除和管理Debian包的工具。所有源自“Debian”的linux的发行版都可使用dpkg命令,比如Ubuntu。语法:dpkg(选项)(参数)选项:-i:安装软件包-r:删除软件包-P:删除软件包的同时删除其配置文件-L:显示于软件包关联的文件–unpack:解开软件包-c:显示软件包内文件列表-configure:配置软件包参数:deb软件包列出deb软件包的…

    2022年5月20日
    33
  • Qt 用QMediaPlayer实现简易播放器

    Qt 用QMediaPlayer实现简易播放器QtMultimedia是Qt的一个重要模块,它提供了许多c++类和QML模块来进行多媒体内容的展示和处理,还提供了一些访问录音机和摄像头的必要的api。本篇中,主要讲述的是C++的实现,而不是QM

    2022年7月2日
    22

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号