0

0

javascript闭包如何使用_它怎样影响变量的作用域【教程】

夜晨

夜晨

发布时间:2026-01-27 15:55:03

|

285人浏览过

|

来源于php中文网

原创

JavaScript闭包使外部函数变量在调用后仍存活,因其内部函数记住了创建时的词法环境;只要内部函数存在,就能持续访问外部变量,依赖词法作用域与函数对象携带环境,而非引用计数。

javascript闭包如何使用_它怎样影响变量的作用域【教程】

闭包是怎么让外部函数变量在调用后依然存活的

JavaScript 闭包的本质,是内部函数记住了它被创建时所处的词法环境。只要这个内部函数还存在(比如被返回、被赋值给变量、被传入事件监听器),它就能持续访问外部函数的变量,哪怕外部函数早已执行完毕。

关键点在于「词法作用域」+「函数对象携带环境」,不是靠引用计数或特殊标记。这意味着:var 声明的变量、let/const 声明的块级绑定,都能被闭包捕获,但行为略有差异(后者会为每次循环迭代创建独立绑定)。

  • 常见错误现象:for (var i = 0; i console.log(i), 100) 输出三个 3 —— 因为所有回调共享同一个 i 变量,循环结束时 i === 3
  • 修复方式:改用 let i(每次迭代新建绑定),或用立即执行函数包裹 var i,或用 setTimeout 的第三个参数传参
  • 性能影响:闭包会阻止外部函数作用域被垃圾回收,如果闭包长期存在且引用了大对象(如 DOM 节点、大型数组),可能引发内存泄漏

如何正确返回一个带状态的闭包函数

最典型的闭包使用场景是封装私有状态。你不需要暴露变量本身,只暴露能操作它的函数。

function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    reset: () => count = 0,
    value: () => count
  };
}

const counter1 = createCounter();
console.log(counter1.value()); // 0
counter1.increment();
console.log(counter1.value()); // 1
  • 每个 createCounter() 调用都生成独立的 count 绑定,counter1counter2 互不影响
  • 不能直接访问 counter1.count —— 它根本不存在于对象上,只存在于闭包环境中
  • 如果返回的是单个函数(如 return () => count++),那它只能做单一操作;返回对象更灵活,但也意味着要管理多个闭包引用同一环境

闭包和 this 绑定容易混淆的点

闭包捕获的是词法作用域里的变量,不包括 thisthis 是运行时决定的,和函数在哪定义无关。所以常有人误以为「闭包能保存 this」,其实不能。

Gambo
Gambo

世界上首个游戏氛围编程智能体

下载

立即学习Java免费学习笔记(深入)”;

  • 错误写法:function foo() { const self = this; return function() { console.log(self.bar); } } —— 这里保存的是 self,不是 this;真正保存 this 需显式绑定
  • 正确做法:用箭头函数(自动继承外层 this)、bind、或在调用前缓存 const that = this
  • Vue/React 类组件中,事件回调常用 handleClick = () => {...} 就是为了避免 this 丢失,这背后也依赖闭包捕获类实例上下文

什么时候不该用闭包——以及替代方案

闭包不是银弹。当逻辑简单、状态无需隔离、或需要频繁创建大量闭包时,它反而增加理解成本和内存开销。

  • 避免在循环中无节制地创建闭包:比如 list.forEach(item => element.addEventListener('click', () => doSomething(item))),如果 list 很大,每个监听器都是独立闭包;可改用事件委托 + datasetevent.target
  • 模块化代码时,ES6 模块本身已提供作用域隔离,不必强行套一层闭包(如 (function(){...})()
  • 现代开发中,class 实例属性 + 方法也能实现类似私有状态的效果(虽然 JS 目前仍靠 #private 字段真正私有),比手动闭包更直观

闭包真正的不可替代性,在于需要「多个函数共享同一份私有状态」且「这份状态不能挂载到对象属性上」的场景——比如防抖函数的定时器 ID、柯里化函数的预置参数、或 Web Worker 通信中的回调队列管理。这些地方,绕不开闭包的环境捕获能力。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

560

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

438

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

776

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

481

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

574

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1091

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

659

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

554

2023.09.20

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

9

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 7.2万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号