JavaScript篇:函数作用域与作用域链探秘

大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了常见的前端开发技术,我还擅长3D开发,熟练使用Three.js进行3D图形绘制,并在虚拟现实与数字孪生技术上积累了丰富的经验,特别是在虚幻引擎开发方面,有着深入的理解和实践。

        我一直认为技术的不断探索和实践是进步的源泉,近年来,我深入研究大数据算法的应用与发展,尤其在数据可视化和交互体验方面,取得了显著的成果。我也注重与团队的合作,能够有效地推动项目的进展和优化开发流程。现在,我担任全栈工程师,拥有CSDN博客专家认证及阿里云专家博主称号,希望通过分享我的技术心得与经验,帮助更多人提升自己的技术水平,成为更优秀的开发者。

目录

函数作用域:你的私人领地

块级作用域的小插曲

作用域链:寻宝地图

闭包:作用域链的魔法应用

常见误区与陷阱

1. 变量提升的坑

2. 循环中的闭包问题

最佳实践建议

总结:掌握你的"秘密基地"


作为前端开发者,我们每天都在和JavaScript的各种概念打交道。今天我要带大家探索JavaScript中两个看似神秘实则有趣的概念——函数作用域和作用域链。它们就像是代码世界里的"秘密基地",理解它们能让你写出更安全、更高效的代码。

函数作用域:你的私人领地

想象一下,函数就像是你自己的房间,而函数作用域就是这个房间的围墙。在房间里(函数内部)声明的变量,就像是你的私人物品,外人(函数外部)是看不到也摸不着的。

function mySecretRoom() {const myDiary = "我今天学会了函数作用域";console.log(myDiary); // 可以访问
}mySecretRoom(); // 输出: "我今天学会了函数作用域"
console.log(myDiary); // 报错: myDiary is not defined

在这个例子里,myDiary就像是放在我房间里的日记本,只有在房间内(函数内部)才能查看。一旦出了房间(函数外部),别人就找不到这本日记了。

块级作用域的小插曲

ES6引入了letconst后,JavaScript也有了块级作用域(用{}包裹的代码块):

if (true) {const myToy = "乐高积木";console.log(myToy); // 可以访问
}
console.log(myToy); // 报错: myToy is not defined

这里myToy就像是我在游乐场临时买的玩具,离开游乐场(代码块)后就找不到了。

作用域链:寻宝地图

现在我们来聊聊更有趣的作用域链。想象你正在玩一个寻宝游戏,作用域链就是你的寻宝地图,告诉你在哪里可以找到需要的"宝物"(变量)。

const globalTreasure = "我是全局宝藏";function outerFunction() {const outerTreasure = "我是外层宝藏";function innerFunction() {const innerTreasure = "我是内层宝藏";console.log(`我找到了: ${innerTreasure}`); // 先找最近的console.log(`我找到了: ${outerTreasure}`); // 然后找上一层的console.log(`我找到了: ${globalTreasure}`); // 最后找全局的}innerFunction();
}outerFunction();

JavaScript查找变量的顺序就像这样:

  1. 先在当前作用域找(我的口袋)

  2. 找不到就去外层作用域找(我的房间)

  3. 还找不到就去更外层找(我的家)

  4. 最后去全局作用域找(小区公共区域)

如果到最后都没找到,就会报错:"宝物不存在"(变量未定义)。

闭包:作用域链的魔法应用

理解了作用域链,闭包就很好解释了。闭包就像是把你的"秘密基地"打包带走的能力。

function createCounter() {let mySecretCount = 0;return function() {mySecretCount++;console.log(`我偷偷数到: ${mySecretCount}`);};
}const counter = createCounter();
counter(); // 我偷偷数到: 1
counter(); // 我偷偷数到: 2

这里mySecretCount本该在createCounter执行完后就消失,但因为返回的函数还在引用它,JavaScript就会把它"打包"保存下来,这就是闭包的魔力。

常见误区与陷阱

1. 变量提升的坑

console.log(myBook); // undefined,而不是报错
var myBook = "JavaScript高级程序设计";

var声明的变量会提升到函数顶部,但赋值不会。这就像是你先告诉大家"我有本书",但书还没拿出来给大家看。

2. 循环中的闭包问题

for (var i = 0; i < 3; i++) {setTimeout(function() {console.log(`我现在的i是: ${i}`);}, 100);
}
// 输出三个: "我现在的i是: 3"

这是因为var没有块级作用域,所有回调函数共享同一个i。改用let就能解决:

for (let i = 0; i < 3; i++) {setTimeout(function() {console.log(`我现在的i是: ${i}`);}, 100);
}
// 输出: "我现在的i是: 0", "我现在的i是: 1", "我现在的i是: 2"

最佳实践建议

  1. 尽量使用constlet:避免var的变量提升和函数作用域带来的困惑

  2. 避免污染全局作用域:把你的"宝物"尽量放在"房间"里,而不是"公共区域"

  3. 合理使用闭包:闭包很强大,但滥用会导致内存泄漏

  4. 保持作用域清晰:过深的嵌套会让代码难以理解

总结:掌握你的"秘密基地"

  • 函数作用域:是你的私人领地,保护变量不被外界干扰

  • 作用域链:是你的寻宝地图,指导JavaScript如何查找变量

  • 闭包:是打包带走你的"秘密基地"的超能力

理解这些概念后,你就能更好地组织代码,避免变量冲突,写出更安全、更易维护的JavaScript代码。下次当你写函数时,不妨想象你正在建造自己的"秘密基地",思考每个变量应该放在哪个位置最合适。

记住,好的开发者不仅是写代码的人,更是代码世界的建筑师!

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

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

相关文章

Robust Kernel Estimation with Outliers Handling for Image Deblurring论文阅读

Robust Kernel Estimation with Outliers Handling for Image Deblurring 1. 论文的研究目标与实际问题意义1.1 研究目标1.2 实际问题与产业意义2. 论文的创新方法、模型与优势2.1 核心思路2.2 关键公式与技术细节2.2.1 非线性模糊模型与能量函数2.2.2 中间潜像更新与IRLS2.2.3…

nginx配置跨域请求,后台不用配置啦,完美

允许全部把域名改* server { listen 22222; server_name localhost; location / { if ($request_method OPTIONS) { add_header Access-Control-Allow-Origin http://localhost:8080; add_header Access-Control-Allow-Headers *; add_header Access-Control-…

[特殊字符] 构建高内聚低耦合的接口架构:从数据校验到后置通知的分层实践

在现代企业系统开发中&#xff0c;接口结构设计的质量直接影响系统的稳定性、扩展性与可维护性。随着业务复杂度上升&#xff0c;单一层次的接口实现往往难以应对功能膨胀、事务一致性、后置扩展等需求。因此&#xff0c;我们提出一种面向复杂业务场景的接口分层模型&#xff0…

MySQL 5.7 实战:JSON 字段提取、Base64 解码与引号问题全解析

一、背景与问题场景 在 MySQL 数据库中&#xff0c;存储 JSON 格式数据&#xff08;如用户行为日志、配置参数、扩展信息&#xff09;的场景日益普遍。当需要从 JSON 字段中提取特定键值&#xff08;如info&#xff09;并进行 Base64 解码时&#xff0c;常遇到以下问题&#x…

1.2.1+1.2.2计算机硬件的基本组成

知识总览 早期冯诺依曼计算机&#xff1a;从人工-》自动 出现原因&#xff1a; 埃尼阿克计算机每执行一条指令都需要人工接线揽&#xff0c;虽然计算机处理的快&#xff0c;但是人工接线可能慢&#xff0c;效率低&#xff0c;于是出现冯诺依曼计算机&#xff0c;把要执行的指…

Spring AI 1.0 GA 正式发布

Spring AI 1.0 GA 正式发布 快速入门核心特性1. **增强型 LLM&#xff08;大语言模型&#xff09;**2. **MCP 协议支持**3. **RAG&#xff08;检索增强生成&#xff09;**4. **评估与监控**5. **智能代理&#xff08;Agents&#xff09;** 下一步计划 VMware Spring 团队 Mark …

亚马逊云科技推出Anthropic新一代模型

5月23日 亚马逊云科技宣布在Amazon Bedrock中推出Anthropic的最新一代模型Claude Opus 4和Claude Sonnet 4。这两款全新混合推理模型能够根据需求在快速响应和深度思考模式间灵活切换&#xff0c;为编码、高级推理和多步骤工作流领域带来全新标准。它们不仅能在复杂的长时间推理…

无人机开启未来配送新篇章

低空物流&#xff08;无人机物流&#xff09;是利用无人机等低空飞行器进行货物运输的物流方式&#xff0c;依托低空空域&#xff08;通常在120-300米&#xff09;实现快速、高效、灵活的配送服务。它是低空经济的重要组成部分&#xff0c;广泛应用于快递配送、医疗物资运输、农…

数据赋能(234)——数据管理——标准化原则

概述 标准化原则的重要性体现在确保数据的格式、结构和命名的一致性。这不仅可以提高数据的质量&#xff0c;还能促进数据的有效共享、交换和利用。以下是标准化原则的重要性的具体体现&#xff1a; 提高数据通用性&#xff1a;遵循数据标准和规范&#xff0c;确保不同系统、…

【Linux笔记】——线程池项目与线程安全单例模式

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a; 【Linux笔记】——简单实习一个日志项目 &#x1f516;流水不争&#xff0c;争的是滔滔不息 一、线程池设计二…

28-FreeRTOS内核控制-延时-临界区

一、FreeRTOS的内核控制接口分析 1.1 函数taskYIELD 此函数用于进行任务切换&#xff0c;此函数本质上是一个宏。它允许当前任务主动放弃CPU使用权&#xff0c;将控制权转移给调度器&#xff0c;以便调度器可以选择另一个就绪任务运行。taskYIELD通常用于协作式多任务系统中&am…

NtfsLookupAttributeByName函数分析之和Scb->AttributeName的关系

第一部分&#xff1a; VOID FindFirstIndexEntry ( IN PIRP_CONTEXT IrpContext, IN PSCB Scb, IN PVOID Value, IN OUT PINDEX_CONTEXT IndexContext ) { 。。。。。。 // // Lookup the attribute record from the Scb. // if (!NtfsLookupAt…

关闭 Ubuntu 20.04 的 GNOME Shell和PulseAudio

一、GNOME Shell GNOME Shell 是 Ubuntu 20.04 默认的桌面环境管理器。关闭它会失去图形界面&#xff08;回到纯终端模式&#xff09;&#xff0c;但可以节省内存和 CPU 资源。 方法 1&#xff1a;临时关闭&#xff08;当前会话生效&#xff09; sudo systemctl stop gdm #…

Dijkstra算法——不带负权的单源最短路径

目录 算法学习 算法原理 稠密图Dijkstra模板 稀疏图Dijkstra模板 练习 1 网络延迟时间 2 到达最后一个房间的最少时间Ⅰ 3 到达最后一个房间的最少时间Ⅱ 4 访问消失节点的最少时间 5 设计可以求最短路径的图类 6 概率最大的路径 7 最小体力消耗路径 8 从第一个节…

【安全攻防与漏洞​】​​Heartbleed漏洞复现与修复

Heartbleed漏洞复现与修复 一、漏洞原理 Heartbleed漏洞&#xff08;CVE-2014-0160&#xff09; 是 OpenSSL 1.0.1 至 1.0.1f 版本中的一个严重内存泄漏漏洞。它源于 TLS 心跳扩展&#xff08;Heartbeat Extension&#xff09;协议中对请求长度字段的未校验&#xff0c;导致攻…

力扣-最大连续一的个数

1.题目描述 2.题目链接 1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 3.代码解答 class Solution {public int longestOnes(int[] nums, int k) {int zero0,length0;for(int left0,right0;right<nums.length;right){if(nums[right]0){zero;}while…

虚拟机Centos7:Cannot find a valid baseurl for repo: base/7/x86_64问题解决

问题 解决&#xff1a;更新yum仓库源 # 备份现有yum配置文件 sudo cp -r /etc/yum.repos.d /etc/yum.repos.d.backup# 编辑CentOS-Base.repo文件 vi /etc/yum.repos.d/CentOS-Base.repo[base] nameCentOS-$releasever - Base baseurlhttp://mirrors.aliyun.com/centos/$relea…

Node.js 库大全

在当今快速迭代的软件开发领域&#xff0c;Node.js 凭借其强大的异步 I/O 处理能力和繁荣的生态系统&#xff0c;已成为全栈开发的核心技术。社区中涌现的无数实用库&#xff0c;如同开发者手中的“瑞士军刀”&#xff0c;能显著提升效率、优化性能并保障安全。本文将系统梳理 …

如何评估物联网框架的交互体验?

物联网&#xff08;IoT&#xff09;技术的快速发展推动了各类物联网框架的涌现&#xff0c;但如何评估其交互体验却成为开发者和企业面临的重要挑战。交互体验不仅涉及用户界面&#xff08;UI&#xff09;的直观性&#xff0c;还包括设备接入效率、协议兼容性、数据交互流畅度以…

3D个人简历网站 6.弹出框

3D个人简历网站 6.弹出框 在components下创建HomeInfo.jsx用于控制主页弹出框信息 输入rafce快速生成代码块 import React from reactconst HomeInfo () > {return (<div>HomeInfo</div>) }export default HomeInfo修改Home.jsx代码实现弹出简单效果 ……re…