作用域和作用域链

news2025/7/20 17:25:27

文章目录

      • 1.作用域(Scope)
        • 1.1 什么是作用域
        • 1.2 全局作用域
        • 1.3 函数作用域
        • 1.3 块级作用域
      • 2. 作用域链
        • 2.1 自由变量
        • 2.2 作用域链
        • 2.3 *自由变量的取值
        • 2.4 作用域与执行上下文的区别
      • 3.总结

1.作用域(Scope)

1.1 什么是作用域

当前的执行上下文,值和表达式在其中“可见”或可被访问。

作用域就是一个独立的地盘,让变量不会外泄、暴露出去。作用域最大的用处就是隔离变量,不同作用域下的同名变量不会有冲突。

ES6之前JavaScript,没有块级作用域,只有全局作用域和函数作用域。ES6的到来,为我们提供了“块级作用域”,可通过let和const来体现。

1.2 全局作用域

在代码中任何地方都能访问到的对象拥有全局作用域。
以下三种情况拥有全局作用域:

  • 最外层函数和在最外层函数外面定义的变量拥有全局作用域
var outVariable = "我是最外层变量"; //最外层变量
function outFun() { //最外层函数
    var inVariable = "内层变量";
    function innerFun() { //内层函数
        console.log(inVariable);
    }
    innerFun();
}
console.log(outVariable); //可以访问: 我是最外层变量
outFun(); //可以访问:  内层变量
console.log(inVariable); //无法访问: inVariable is not defined
innerFun(); //无法访问: innerFun is not defined
  • 所有未定义直接赋值的变量自动声明为用于全局作用域
function outFun2() {
    variable = "未定义直接赋值的变量";
    var inVariable2 = "内层变量2";
}
outFun2();//要先执行这个函数,否则根本不知道里面是啥
console.log(variable); //未定义直接赋值的变量
console.log(inVariable2); //inVariable2 is not defined
  • 所有window对象的属性拥有全局作用域
    window对象的内置属性都拥有全局作用域,例如window.name、window.name、window.localtion、window.top等

全局作用域的弊端:如果我们写了很多行JS代码,变量定义都没有用函数包括,那么他们就全部在全局作用域中。这样就会污染全局命名空间,容易引起命名冲突。这就是为什么jQuery、Zepto等库的源码,所有的代码都会放在(function(){…})中。因为放在里面的所有变量,都不会被外泄和暴露,不会污染到外面,不会对其他库和JS脚本造成影响。这是函数作用域的一个体现。

1.3 函数作用域

指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到。

function doSomething(){
    var stuName="zhangsan";
    function innerSay(){
        console.log(stuName);
    }
    innerSay();
}
console.log(stuName); // 无法访问:脚本错误
innerSay(); //无法访问: 脚本错误

注:块语句(大括号‘{}’中间的语句),如if 和switch条件语句,或for 和whlie循环语句,不像函数,他们不会创建一个新的作用域

if (true) {
    // 'if' 条件语句块不会创建一个新的作用域
    var name = 'Hammad'; // name 依然在全局作用域中
}
console.log(name); // 可以访问:'Hammad'

1.3 块级作用域

块级作用域可通过let和const声明,所声明的变量在指定块的作用域外无法被访问

{
   var a=1
}
        console.log(a)

在这里插入图片描述

{
  let a=1
 }
        console.log(a)

在这里插入图片描述

2. 作用域链

2.1 自由变量

当前作用域中没有定义的变量,称为自由变量。

2.2 作用域链

访问变量时,自己的作用域中没有,一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃,这种一层一层的关系,就是作用域链。

var a = 100
function f1() {
    var b = 200
    function f2() {
        var c = 300
        console.log(a) // 100 自由变量,顺作用域链向父作用域找
        console.log(b) // 200 自由变量,顺作用域链向父作用域找
        console.log(c) // 300 本作用域的变量
    }
    f2()
}
f1()

2.3 *自由变量的取值

例1:

var x = 10
function fn() {
    console.log(x)
}
function show(f) {
    var x = 20;
    (function () {
        f() // 10,而不是 20
    })()
}
show(fn)

如上代码,取自由变量x的值时,无论fn函数在哪里调用,都要到创建fn函数的那个作用域中取。

自由变量的取值(静态作用域):要到创建爱你这个函数的那个域中取值。这里强调的是"创建",而不是“调用”。
例2:

const food = "rice";
const eat = function () {
    console.log(`eat ${food}`);
};
(function () {
    const food = "noodle";
    eat(); // eat rice
})();

eat函数在创建时,它的父级上下文为全局上下文,所以food的值为rice。
若要打印为noodle,需做如下修改:

const food = "rice";
(function () {
    const food = "noodle";
    const eat = function () {
        console.log(`eat ${food}`);
    };
    eat(); // eat noodle
})();

2.4 作用域与执行上下文的区别

JavaScript属于解释型语言,执行分为解释和执行两个阶段:
解释阶段:

  • 词法分析
  • 语法分析
  • 作用域规则确定

执行阶段

  • 创建执行上下文
  • 执行函数代码
  • 垃圾回收

JavaScript解释阶段便会确定作用域规则,因此作用域在函数定义时就已经确定了
执行上下文最明显的就是this的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。

总结: 执行上下文在运行时确定,随时可能改变,作用域在定义时就确定,并且不会改变

3.总结

什么是作业域 ?

ES5 中只存在两种作用域:全局作用域和函数作用域。

JavaScript 中,我们将作用域定义为一套规则,这套规则用来管理引擎如何在当前作用域以及嵌套子作用域中根据标识符名称进行变量(变量名或者函数名)查找。ES6 新增了块级作用域。

什么是作用域链 ?

当访问一个变量时,编译器在执行这段代码时,会首先从当前的作用域中查找是否有这个标识符,如果没有找到,就会去父作用域查找,如果父作用域还没找到继续向上查找,直到全局作用域为止。

而作用域链,就是有当前作用域与上层作用域的一系列变量对象组成,它保证了当前执行的作用域对符合访问权限的变量和函数的有序访问。

作用域链有一个非常重要的特性,那就是作用域中的值是在函数创建的时候,就已经被存储了,是静态的

所谓静态,就是说作用域中的值一旦被确定了,永远不会变。**函数可以永远不被调用,但是作用域中的值在函数创建的时候就已经被写入了,**并且存储在函数作用域链对象里面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/37725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

easy-rules规则引擎最佳落地实践

写作目的 这是一个头部互联网公司中的一个问题。因为有很多业务产品线,作为一个新人或者团队外的人员是很难区分不同的产品线之间的区别的,因此需要给某个产品线一个描述。但是随着业务的发展,产品线下可能又根据某个字段进一步划分&#xf…

招生CRM系统|基于Springboot实现培训机构招生CRM管理系统

作者主页:编程指南针 作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

Mongodb操作基础 分片

Mongodb分片 MongoDB分片是MongoDB支持的另一种集群形式,它可以满足MongoDB数据量呈爆发式增长的需求。当MongoDB存储海量的数据时,一台机器可能无法满足数据存储的需求,也可能无法提供可接受的读写吞吐量,这时,我们就…

基于内容的个性化推荐算法

一、什么是推荐算法 随着移动互联网的高速发展与智能手机的普及,海量的有用信息虽然为人们提供了更多的价值,然而信息的泛滥也意味着为了寻找合适的信息必须付出更多的时间成本。事实上,有时候仅仅是浏览和简单的查询来寻找有用的信息变得相…

「强烈收藏」Python第三方库资源大全,1000+工具包

前言 awesome-python 是 vinta 发起维护的 Python 资源列表,内容包括:Web 框架、网络爬虫、网络内容提取、模板引擎、数据库、数据可视化、图片处理、文本处理、自然语言处理、机器学习、日志、代码分析等。 (文末送读者福利) …

超全!程序员必备的20个学习网站,看这一篇就够了!

之前一直想出个程序员学习清单,终于腾出时间弄出来了,也趁此机会整理了收藏夹。 此篇对于新手程序员比较有用,技术老鸟们也可以查缺补漏。 话不多说,纯纯干货呈上,赶紧点个赞收藏,以后会用得上!…

CMake中include_directories的使用

CMake中include_directories命令用于在构建(build)中添加包含目录,其格式如下: include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]) 将给定的目录添加到编译器(compiler)用于搜索包含文件的目录。相对路径被解释为相对于当前源目录。 包含目录被添加到当前C…

【网络】tcpdump、Wireshark 案例超详细介绍

文章目录网络分层应用层找到服务器的 IP查接口、对象的耗时删除指定网站的Cookie表示层、会话层tcpdump、wireshard传输层telnet: 路径可达性测试nc: 路径可达性测试netstat:查看当前连接状态iftop:查看当前连接的传输速率netstat -s: 查看丢包和乱序的统…

万字 HashMap 详解,基础(优雅)永不过时

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 前言 大家好,我是小彭。 在上一篇文章里,我们聊到了散列表的整体设计思想,在后续几篇文章里,我们将以 Java 语言为例&#xff…

【王道计算机组成原理Note】5.5 指令流水线

5 指令流水线 5.1 指令流水的定义 一条指令的执行过程可以分成多个阶段(或过程)。根据计算机的不同,具体的分法也不同。 取指:根据Pc内容访问主存储器,取出一条指令送到IR中。分析:对指令操作码进行译码,按照给定的寻…

Visio 安装暴雷记录

Visio 安装记录起因: office2016家庭学生版中,安装visio2021后,插入word的vsdx图形右键显示unkown类型,无法识别,给学习工作带来很多麻烦!   搜查一圈没找到对应可用的方法,想着可能是visio20…

MobPush for Flutter

集成准备 这是一个基于 MobPush 功能的扩展的 Flutter 插件。使用此插件能够帮助您在使用 Flutter 开发应用时,快速地实现推送功能。 在pubspec.yaml文件中加入下面依赖 dependencies:mobcommonlib:mobpush_plugin: 然后执行:flutter packages get 导…

倍增(小试牛刀)

二分每次折半,倍增每次2的倍数 原理先存储每个小区间的最值也就是初始化,之后直接查询 1. 把数列按倍增分成小区间 对数列的每个元素,把从它开始的数列分成长度为1、2、4、8、…的小区间。下图给出了一个分区的例子,它按小区间…

java--JVM

JVM1.JVM的内存结构2.哪些部分会出现内存溢出3.方法区与永久代、元空间之间的关系4.JVM内存参数5.JVM垃圾回收算法(1)标记清除(2)标记整理(3)标记复制6.GC和分代回收算法7.三色标记和并发漏标问题8.垃圾回收…

【分布式技术专题】「Zookeeper中间件」给大家学习一下Zookeeper的”开发伴侣”—Curator-Framework(基础篇)

CuratorFramework基本介绍 CuratorFramework是Netflix公司开源的一套Zookeeper客户端框架,它作为一款优秀的ZooKeeper客户端开源工具,主要提供了对客户端到服务的连接管理和连接重试机制,以及一些扩展功能,它解决了很多ZooKeeper…

Linux服务器配置与管理(基于Centos7.2)任务目标(四)

文章目录一、任务目标二、任务资讯三、任务实施3-1.RPM软件包管理3-2.YUM方式安装软件一、任务目标 实施该工单的任务目标如下: 知识目标 1.了解RPM提供的功能。 2.了解YUM相对于RPM所具有的优点。 能力目标 1.能够通过RPM安装及管理软件包。 2.能够通过YUM安装及管…

uni-app —— 小程序加入购物车实现过程

文章目录 前言一、示意图二、整体实现思路三、实现过程 1.加入购物车2.获取当前用户购物车信息3.解决数据获取不及时的问题总结前言 前文已经讲解了如何实现商品规格的选择,那么接下来就应该将用户选中的商品加入购物车啦!那么如何实现呢?请…

[附源码]计算机毕业设计JAVA儒家文化网站

[附源码]计算机毕业设计JAVA儒家文化网站 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis M…

FilterListenerAjax的介绍

目录 一、Filter 1、Filter概述 2、过滤器链 二、Listener 三、Ajax 1、基本介绍 2、快速入门案例 3、axios 4、JSON 一、Filter 1、Filter概述 ▶ 过滤器 Filter 表示过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。过滤器可以把对资源的请…

Centos--基于Jdk1.8环境安装+卸载Jenkins

基础准备 本人选择的安装的环境基于jdk1.8 操作系统:Centos7.9 java: 1.8.0_262 检查是否有旧版本 $rpm -ql jenkins 如果有老版本可以卸载后,再执行后面的安装步骤 卸载 jenkins $rpm -e jenkins —删除遗留文件: $find / -iname jenkins | xa…