JavaScript作用域与闭包

ops/2025/2/19 3:37:46/

一 作用域

在JavaScript中,作用域(Scope)指的是变量和函数的可访问性范围。在JavaScript中,作用域有全局作用域和局部作用域之分。

 

  1. 全局作用域(Global Scope):全局作用域指的是在代码中任何位置都可以访问的变量和函数。在浏览器环境中,全局作用域通常是指window对象。在全局作用域中声明的变量和函数可以被任何代码访问。
    javascript">let globalVar = 'I am a global variable';function globalFunction() {console.log('I am a global function');
    }console.log(globalVar); // 输出 'I am a global variable'
    globalFunction(); // 输出 'I am a global function'
  2. 局部作用域(Local Scope):局部作用域指的是在函数内部声明的变量和函数,只能在函数内部访问。每个函数都会创建一个新的局部作用域,函数内部的变量和函数只能在该函数内部访问。
    javascript">function localFunction() {let localVar = 'I am a local variable';console.log(localVar); // 在函数内部可以访问
    }localFunction();
    console.log(localVar); // 报错,localVar在函数外部不可访问
  3. 作用域链(Scope Chain):当代码在嵌套作用域中执行时,JavaScript会按照作用域链的顺序查找变量。如果一个变量在当前作用域中找不到,JavaScript会沿着作用域链一级一级地向上查找,直到找到该变量或者到达全局作用域。
    javascript">let outerVar = 'I am from outer scope';function outerFunction() {let innerVar = 'I am from inner scope';function innerFunction() {console.log(outerVar); // 可以访问外部函数的变量console.log(innerVar); // 可以访问内部函数的变量}innerFunction();
    }outerFunction();

    作用域在JavaScript中起着非常重要的作用,它决定了变量和函数的可访问性,帮助我们避免命名冲突和提高代码的可维护性。在理解作用域的基础上,可以更好地编写和理解JavaScript代码。

二 闭包 

闭包是指在一个函数内部可以访问其外部作用域的局部变量的函数。

由于在 JavasSript 中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成"定义在一个函数内部的函数"。

所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

 

闭包的优点包括:

  1. 可以访问外部函数的局部变量,提高了代码灵活性和可复用性。
  2. 可以实现封装和隐藏数据,保护数据不被外部访问和修改。
  3. 可以延长变量的生命周期,使得变量在外部函数执行完后仍然可以被访问。
  4. 可以实现回调和事件处理等功能。

闭包的缺点包括:

  1. 可能会导致内存泄漏,因为闭包中引用了外部函数的变量,导致这些变量无法被垃圾回收。
  2. 闭包的层级嵌套过多可能会增加程序的复杂度,降低代码的可读性和可维护性。
  3. 闭包对性能有一定影响,因为每次调用闭包都需要创建一个新的执行环境。
  4. 有可能因为闭包中对外部变量的引用导致意料之外的结果,需要特别注意作用域和闭包的关系。

闭包在编程中有许多实际的用途,以下是一些常见的用途和案例:

  1. 封装私有变量和方法:利用闭包可以创建私有变量和方法,实现信息隐藏和封装,例如模拟类的私有属性和方法。
    javascript">function createCounter() {let count = 0;return {increment: function() {count++;},getCount: function() {return count;}};
    }let counter = createCounter();
    counter.increment();
    console.log(counter.getCount()); // 输出1
    ​​​
  2. 保存状态:在函数执行完毕后,闭包可以保存函数内部的状态,使得变量的值在函数外部仍然可访问和修改。
    javascript">function createTimer() {let seconds = 0;function incrementTimer() {seconds++;console.log(`Timer: ${seconds} seconds`);}return incrementTimer;
    }let timer = createTimer();
    timer(); // 输出 Timer: 1 seconds
    timer(); // 输出 Timer: 2 seconds
  3. 回调函数:在事件处理、异步编程等场景中常用闭包来实现回调函数,保持函数内部对外部变量的引用。
    javascript">function fetchData(url, callback) {fetch(url).then(response => response.json()).then(data => {callback(data);});
    }function processData(data) {console.log(data);
    }fetchData('https://api.example.com/data', processData);
  4. 模块模式:利用闭包实现模块化开发,将相关的变量和方法封装在闭包内部,提供对外的接口,以防止全局污染。
    javascript">let module = (function() {let privateVar = 10;function privateFunction() {return privateVar;}return {publicVar: 20,publicFunction: function() {return privateFunction() + this.publicVar;}};
    })();console.log(module.publicFunction()); // 输出 30
    ​​​​​​​

http://www.ppmy.cn/ops/158793.html

相关文章

ASP.NET Core SixLabors.ImageSharp v1.0 的图像实用程序类 web示例

这个小型实用程序库需要将 NuGet SixLabors.ImageSharp包(版本 1.0.4)添加到.NET Core 3.1/ .NET 6 / .NET 8项目中。它与Windows、Linux和 MacOS兼容。 这已针对 ImageSharp v3.0.1 进行了重新设计。 它可以根据百万像素数或长度乘以宽度来调整图像大…

C++17中的clamp函数

一、std::clamp() 其实在前面简单介绍过这个函数&#xff0c;但当时只是一个集中的说明&#xff0c;为了更好的理解std::clamp的应用&#xff0c;本篇再详细进行阐述一次。std::clamp在C17中其定义的方式为&#xff1a; template< class T > constexpr const T& cl…

二叉树(C语言版)

文章目录 二叉树完全二叉树和满二叉树二叉搜索树基本操作实现代码运行结果 分析红黑树2-3-4树(理论模型)红黑树(实际实现) 二叉树 树是一种层次结构&#xff0c;它在现实生活中是广泛存在的&#xff0c;比如&#xff1a;族谱(family tree)&#xff0c;组织机构&#xff0c;目录…

【个人开发】deepseed+Llama-factory 本地数据多卡Lora微调

文章目录 1.背景2.微调方式2.1 关键环境版本信息2.2 步骤2.2.1 下载llama-factory2.2.2 准备数据集2.2.3 微调模式2.2.4 微调脚本 2.3 踩坑经验2.3.1 问题一&#xff1a;ValueError: Undefined dataset xxxx in dataset_info.json.2.3.2 问题二&#xff1a; ValueError: Target…

STM32——HAL库开发笔记19(串口中断接收实验)(参考来源:b站铁头山羊)

本实验&#xff0c;我们以中断的方式使得串口发送数据控制LED的闪烁速度&#xff0c;发送1&#xff0c;慢闪&#xff1b;发送2&#xff0c;速度正常&#xff1b;发送3&#xff0c;快闪。 一、电路连接图 二、实现思路&CubeMx配置 1、实现控制LED的闪烁速度 uint32_t bli…

Redisson分布式锁和同步器完整篇

Redisson分布式锁和同步器完整篇 在分布式系统中&#xff0c;如何确保多个服务实例之间的数据一致性和资源协调是一个关键挑战。Redisson作为基于Redis的Java客户端&#xff0c;提供了一套完整的分布式锁和同步器解决方案&#xff0c;帮助开发者轻松应对这些挑战。 本文将深入…

DeepSeek-R1的使用及图解

目录 1 本地部署 DeepSeek 本地部署 DeepSeek 的优势 DeepSeek 本地部署的三大步骤 2 大语言模型基础 LLM 基础概念解析 大模型与特定数据集模型的区别 扩展规律&#xff08;Scaling Laws&#xff09; Transformer 架构概述 LLM 训练的核心方法 预训练阶段&#xff08…

在 PyCharm 中接入deepseek的API的各种方法

在 PyCharm 中接入 DeepSeek 的 API&#xff0c;通常需要以下步骤&#xff1a; 1. 获取 DeepSeek API 密钥 首先&#xff0c;确保你已经在 DeepSeek 平台上注册并获取了 API 密钥&#xff08;API Key&#xff09;。如果没有&#xff0c;请访问 DeepSeek 的官方网站注册并申请 …