快速通关作用域!

news/2025/6/29 8:48:15

作用域

变量作用域

一个变量的作用域(scope)是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在 JavaScript 代码中的任何地方都是可以访问的。然而在函数内声明的变量只能在函数体内访问,它们是局部变量,作用域是局部性的。函数参数也是局部变量,它们只能在函数体内访问。

在函数体内,局部变量的优先级高于同名的全局变量。如果在函数内声明一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量就会被局部变量所覆盖。

var scope = 'global'function checkscope() {var scope = 'local'return scope
}checkscope() // 'local'

函数作用域和声明提前

JavaScript 的函数作用域是指在函数内声明的所有变量在函数体内任何地方都是可以访问的,这意味着变量在声明之前就可以访问了。JavaScript 的这个特性被非正式的称为声明提前(hoisting),即 JavaScript 函数内声明的所有变量(不包含赋值)都被提升至函数体的顶部。声明提前这步操作是在 JS 引擎预编译时进行的,也就是在代码开始运行之前。

function test() {var i = 2if (true) {var j = 0for (var k = 0; k < 10; k++) {}console.log(k) // 10}console.log(j) // 0
}test()

以上代码,在不同位置定义了变量 i、j、k,但是它们都在同一个函数作用域内。由于声明提前的特性,这三个变量在函数体内任何地方都是可以访问的。

声明提前后相当于下图的效果:

function test() {var ivar kvar ji = 2if (true) {j = 0for (k = 0; k < 10; k++) {}console.log(k) // 10}console.log(j) // 0
}test()

作用域链

如果将一个局部变量看做是自定义实现的对象的属性的话,那么可以换个角度来解读变量作用域。每一段 JavaScript 代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)。这个作用域链是一个对象或者链表,这组对象定义了这段代码作用域中的变量。在这里涉及到了链表的概念,本来也是打算留在数据结构算法再讲的,但是这里用到了就简单介绍一下什么是链表。

:::tip 超前知识
链表是有序的数据结构,链表中的每个部分称为节点。每个节点都包含两个属性,一个是 value 主要存放当前节点的数据,另外一个是 next 主要用来指向下一个节点。
:::

作用域链查找过程

var x = 10
var y = 10function a() {var y = 20function b() {var y = 30console.log(x)}b()
}a()

从上面的代码我们可以得出,全局对象 window 上存在 x 和 y 属性。当前存在三个作用域,一个是全局作用域,一个作用域 a、另外一个是作用域 b。

链表结构如下

链表代码如下

var window = {value: {x: 10,y: 10},next: null
}var a = {value: {y: 20},next: window
}var b = {value: {x: 30},next: a
}

当 JavaScript 需要查找变量 x 的值的时候(这个过程称为变量解析 variable resolution),它会从链表的第一个对象开始查找,如果这个对象有一个名为 x 的属性,则会直接使用这个属性的值,如果第一个对象中不存在名为 x 的属性,则会继续查找下一个对象(通过链表节点的 next),以此类推(链表的最后一个对象就是全局对象)。如果作用域链上没有任何一个对象含有 x 的属性,那么就会认为这段代码的作用域链上不存在 x,并最终抛出一个引用错误异常 Uncaught ReferenceError: x is not defined。

作用域链创建过程

当定义一个函数时,它实际上会保存一个作用域链(每个函数都有独立的作用域链)。

正常形式

var x = 10
var y = 10function a() {var x = 20
}

链表形式

var window = {value: {x: 10,y: 10},next: null
}var a = {value: null,next: window
}

例如上图,我们定义了函数 a,这个时候我们还没有进行调用。函数 a 的作用域链为:a -> window

正常形式

var x = 10
var y = 10function a() {var x = 20
}a()

链表形式

var window = {value: {x: 10,y: 10},next: null
}var a = {value: {x: 20},next: window
}

当调用这个函数时,它就会创建一个新执行上下文环境(对象)来存储它的局部变量,并将这个对象添加至刚才所保存的作用域链上。

原文链接:菜园前端

文章来源:https://blog.csdn.net/qq2603375880/article/details/130993589
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:https://dhexx.cn/news/show-4643149.html

相关文章

链表排序(自己鼓捣出一种递归建表)

递归建表 是不是很优雅&#xff01; struct ListNode {int val;ListNode *next;ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), next(nullptr) {}ListNode(int x, ListNode *next) : val(x), next(next) {}};ListNode* Create(int n) {if(!n) return NULL…

网络安全工具合集

首先&#xff0c;恭喜你发现了宝藏。 本文章集成了全网优秀的开源攻防武器项目&#xff0c;包含&#xff1a; 信息收集工具&#xff08;自动化利用工具、资产发现工具、目录扫描工具、子域名收集工具、指纹识别工具、端口扫描工具、各种插件....etc...&#xff09; 漏洞利用…

使用Fiddler进行Mock测试的原理和方法

叨叨在前&#xff1a;之前工作中&#xff0c;做的纯接口测试&#xff0c;当时公司有自己的Mock平台&#xff0c;可以进行接口Mock测试。后来离开公司后&#xff0c;再想做Mock测试&#xff0c;就只能使用开源工具&#xff0c;或者自己用Flask写Mock了。今儿整理一下&#xff0c…

Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较以及为什么禁止使用double直接构造BigDecimal

场景 阿里Java开发手册嵩山版中明确指出&#xff1a; 1、BigDecimal的等值比较应使用compareTo()方法&#xff0c;而不是equals()方法 equals()方法会比较值和精度&#xff08;1.0与1.00返回结果为false&#xff09;,而compareTo()则会忽略精度 2、禁止使用构造方法BigDeci…

DebugView的使用

目录 一、前言二、本机调试1.DebugView程序文件说明2.OutputDebugString函数使用3.示例程序4.远程调试 三、问题与注意事项四、小结 一、前言 DebugView是windows下的一款调试工具,可以捕获程序输出的日志,分为64位和32位,支持应用层和内核层的日志捕获,利用它排除bug是个不错的…

leetcode 1030. 距离顺序排列矩阵单元格

题目描述解题思路执行结果 leetcode 1030. 距离顺序排列矩阵单元格. 题目描述 距离顺序排列矩阵单元格 给定四个整数 rows , cols , rCenter 和 cCenter 。有一个 rows x cols 的矩阵&#xff0c;你在单元格上的坐标是 (rCenter, cCenter) 。 返回矩阵中的所有单元格的坐标&…

typedef 和 # define 用法区别

typedef 和 # define 用法区别 前言1. 原理不同1.1 typedef int * int_ptr;与#define int_ptr int * 详细讲解 2. 功能不同3. 作用域不同 前言 博主在牛客网上看到了一道有关typedef和# define题目。发现有很多初学的小伙伴对两者的用法不是特别清楚&#xff0c;所以博主在这总…

系统架构设计师笔记第8期:信息加解密技术

信息加解密技术是指用于保护数据安全性和隐私的技术方法。随着信息技术的发展和网络通信的普及&#xff0c;信息加解密技术也得到了广泛的应用和不断的发展。下面是信息加解密技术发展的主要阶段和趋势&#xff1a; 古典加密技术&#xff1a;古典加密技术是信息加解密技术的起…

Servlet域对象

Servlet介绍&#xff1a; Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术&#xff1b; Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&#xff0c;将来我们需要定义Servlet类实现Servlet接口&#xff0c;并 由web服务器运行Servl…

一、人像分割

开源PP-HumanSegl模型,提供了三个高质量的人像分割模型:有应用于服务端GPU部署的PP-HumanSegl模型,有适用于移动端的轻量PP-HumanSeg模型,还有能够在浏览器部署的超轻量模型PP-HumanSegs模型。 近期百度视频会议 上线了虚拟背景功能,支持在网页端视频会议时进行背景切…