-
我在 Python 的循环里批量造了一串函数,每个本该记住自己那一轮的编号,结果调用时它们却异口同声地全返回了最后一个数,排查半天发现闭包记住的是变量本身、而不是当时那个值的深度复盘
我有个需求:根据一个列表批量生成一串回调函数,每个被调用时应返回它对应的索引——第 0 个返回 0、第 1 个返回 1。我很自然地在 for 循环里用 lambda 一个个造出来,自觉天衣无缝。可一调用就傻眼:这串函数无论调哪一个,返回的全是同一个数——最后一个索引!它们仿佛集体失忆,谁也没记住自己出生那一刻的编号,而是异口同声报出同一个数。我盯着那段再正常不过的循环百思不得其解:明明每轮 i 都…- 0
- 0
-
我在 for range 循环里起了一批 goroutine 并发处理任务,结果它们全都处理了同一个、也就是最后一个任务:一次 Go 循环变量被复用、闭包捕获到的全是最后一个值的深度复盘
我要并发处理一批任务,for range 遍历任务列表、每个任务起一个 goroutine 去处理。结果诡异:明明有 10 个不同任务,日志里 10 个 goroutine 处理的全是同一个、也就是最后一个任务,前 9 个一个都没处理。查清才发现:在 Go 1.22 之前,for range 的循环变量 task 是整个循环复用的同一个变量,每轮只是赋新值;而 goroutine 闭包捕获的是这个…- 0
- 0
-
我在循环里批量创建了一组函数,本想让它们各自记住循环时的值,结果调用时它们全都返回了循环结束后那个最终值,我对着 Python 闭包捕获的是变量而非值这个延迟绑定的坑排查大半天的复盘
一个让我对 Python 闭包到底记住了什么彻底搞明白的坑,诡异在我分明在循环里给每个函数都用了当时的循环值,可这些函数全都失忆了——记住的不是各自创建时的值而是所有函数共享的循环结束后同一个最终值。要在循环里批量创建一组函数,每个应记住对应的循环值:for i in range(3): funcs.append(lambda: i)。期望调用得到 [0,1,2],实际却是 [2,2,2] 全是 …- 2
- 0
-
我在 for 循环里起了一堆 goroutine 处理每个元素,结果它们全在处理同一个、还是最后一个,我对着循环变量被闭包捕获排查了大半天的复盘
用 Go 写批处理,想为切片每个元素并发起一个 goroutine,经典的 for + go 写法,行云流水。结果目瞪口呆:10 个元素起了 10 个 goroutine,处理的却全是同一个、还是最后一个,前 9 个一个没处理。盯着代码反复看,循环明明遍历了每个元素,凭什么 goroutine 全拿到最后一个?排查大半天才理解 Go 1.22 之前坑了无数人的经典陷阱:for 循环变量被闭包捕获。…- 0
- 0
-
我在 Python 的循环里批量创建了一串函数,本以为每个都记着各自的循环值,结果调用时它们竟然全都返回了同一个最后的值,我排查了大半天的复盘
我在 Python 循环里用 lambda 批量创建了一串函数装进列表,本以为它们会分别返回 0、1、2,结果挨个调用竟全返回 2——循环的末值,每个函数都"失忆"了。深挖才懂:Python 闭包是"延迟绑定(late binding)"——lambda 捕获的不是"创建时 i 的值",而是"变量 i 本身"的引用,它…- 0
- 0
-
我在循环里用 var 注册了几个回调,本想让它们各自打印 0、1、2,结果它们齐刷刷全打印了 3,我盯着这个诡异的结果排查了大半天的深度复盘
我在 for 循环里用 var 注册了几个 setTimeout 回调,本想让它们各自打印 0、1、2,结果它们齐刷刷全打印了 3。这几个回调明明在 i 不同时刻创建,怎么全记住了循环结束后的 3?深究才懂是两个机制叠加:一,var 是函数作用域不是块作用域,整个循环只有一个共享的 i;二,闭包捕获的是变量(引用)而非那一刻的值。加上回调是异步延迟执行的——执行时循环早跑完、共享的 i 已是 3,…- 2
- 0
-
给五个按钮绑点击事件,点哪个都弹出"第 5 个":我在 JavaScript 里被一个 for 循环里的 var 闭包坑到怀疑人生,以及作用域与闭包的全面复盘
动态生成五个按钮,点第几个就弹"第几个"——结果点哪个都弹"第 5 个"。绑定时打印 i 明明是 0~4,执行时却全变 5。根因是 var 函数作用域:整个循环只有一个 i,而五个闭包捕获的是这个变量的引用而非值。这篇复盘讲清原理、let 一字之差的正解、IIFE 等老办法,并延伸到 setTimeout 异步亲戚坑,以及闭包既是坑也是 JavaScript…- 0
- 0
-
用户数据莫名串味:Python 可变默认参数避坑复盘
这是我职业生涯里排查得最久也最毛骨悚然的一个 bug:一个 Python 写的接口偶尔会串味——A 用户请求自己的数据,返回里却莫名混进了 B 用户的几条记录。注意是偶尔,大部分时候都正常,只在生产高峰期零星出现,测试环境怎么都复现不了。对处理用户数据的系统来说这种串味最恐怖,它不是崩溃不是报错,而是静默的数据污染。我查了整整两天,一度怀疑是缓存串了、连接池复用了脏连接、是并发竞态,把能想到的高大…- 0
- 0
-
方法当回调 this 就丢:JS this 指向避坑复盘
有个 JavaScript 的类里有个方法,逻辑是处理点击事件然后更新自己的一个属性:class Counter { count = 0; handleClick() { this.count++ } },然后我把这方法当回调绑到按钮上 button.addEventListener(click, counter.handleClick)。本地一测点击按钮啪一声控制台红字:Cannot read …- 0
- 0
-
所有按钮都触发最后一项:JS 闭包与 var 陷阱
一个再简单不过的需求:页面动态渲染一排按钮,每个对应一条数据,点击弹出你选了第几项。我三下五除二写完,本地点第一个按钮弹出的却是最后一项,点第二个还是最后一项,点哪个通通是最后一项,功能演示当场翻车,而我盯着那段自认为毫无问题的代码百思不得其解。把循环变量打印出来才看清真相:每个按钮的点击回调里拿到的 i 全都是循环结束后的最终值,罪魁祸首是那个我用了无数次从没多想的关键字 var——它声明的 i…- 0
- 0
-
JavaScript 内存泄漏排查实战:定时器、闭包、缓存与游离 DOM
一个 Node 服务三天一 OOM、靠定时重启续命,推上去彻查后才发现:JS 有 GC 也照样漏内存,因为 GC 回收的是不可达对象,而你忘了断开的引用让它一直可达。从五类最高发的泄漏面孔(未清的定时器监听器、捕获大对象的闭包、只增不删的全局缓存、游离 DOM、囤进全局的变量)讲到三次堆快照对比法,再到追 Retainers 引用链的固定排查流水线。- 0
- 0
-
彻底搞懂 JavaScript 闭包:从作用域链到内存泄漏的完全指南
先看一段几乎每个 JavaScript 面试都会出现的代码,如果你能一眼说清它的输出,以及为什么,那这篇文章对你而言是复习;如果你还会犹豫,那它会帮你把"闭包"这件事彻底钉死在脑子里。 for (var i = 0; i < 3; i++) { setTimeout(function () { console.log(i); }, 0); } // 输出:3 3 3 ——…- 0
- 0
-
Python 装饰器深度指南:从原理到高级实战用法
装饰器(decorator)是 Python 里最有"Python 味"的特性之一,也是新手觉得最"玄"的语法 —— 一个 @ 符号往函数头上一放,函数就莫名其妙多了功能。但其实装饰器一点都不玄,它背后是三个非常朴素的概念的组合。这篇从原理讲起,一步步推到 functools.wraps、带参数的装饰器、类装饰器、多装饰器叠加的执行顺序,再过一遍标准库里那些…- 0
- 0
闭包
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!













