202、【Agent】【OpenCode】JS 语法:闭包捕获还是参数传递

202、【Agent】【OpenCode】JS 语法:闭包捕获还是参数传递 【声明】本博客所有内容均为个人业余时间创作所述技术案例均来自公开开源项目如GithubApache基金会不涉及任何企业机密或未公开技术如有侵权请联系删除标题202、【Agent】【OpenCode】JS 语法闭包捕获还是参数传递背景上篇 blog【Agent】【OpenCode】JS 语法setTimeout 七种常用形式盘点了 setTimeout 的七种常用形式本质是三个自由度的组合回调怎么写箭头内联 / 函数引用 / 递归、数据怎么给闭包捕获 / 第三参数快照 / 不喂、生命周期怎么管clearTimeout / unref / 延迟 0。其中形式①内联箭头 闭包与形式②函数引用 第三参数恰好是给回调喂数据的两种相反方式——一个靠闭包实时引用一个靠参数注册时快照。本篇专门展开这两种方式的取舍什么时候可以用闭包什么时候必须传参OpenCode先看两种写法的直观对比// 形式①闭包捕获实时引用for(vari0;i3;i)setTimeout(()console.log(i),0)// 3 3 3// 形式②第三参数传值注册时快照for(vari0;i3;i)setTimeout(console.log,0,i)// 0 1 2核心差异实时引用 vs 值快照闭包捕获的是变量本身回调执行那一刻才去读变量看到的是当时的最新值传参传的是当时的快照基本类型拷贝值注册那一刻就固化这个差异是后面所有取舍准则的根源。什么时候用闭包条件说明① 变量就在回调定义处的作用域内能直接看见就能直接捕获② 要读当前值变量在回调执行前不变或就是要最新值③ 回调一次性内联比如延迟一次就执行的 setTimeout④ 无循环/复用/生命周期顾虑不涉及每轮各取一值长期持有等场景本案例为什么用闭包200 篇的thread.ts:197-199setTimeout((){client.call(checkUpgrade,{directory:cwd})},1000)client/cwd就在 handler 闭包作用域内条件①回调一次性、执行于启动后 1 秒要的就是当时的 client/cwd条件②③无循环、无复用条件④。四个条件全满足闭包是自然选择。什么时候必须传参条件说明① 变量不在回调定义的作用域是别的函数/模块的局部回调定义处看不见② 需要值快照循环里每个定时器要各自的值见上方 var 陷阱输出③ 回调要独立复用 / 可传递回调是单独命名函数、交给别的模块只能靠参数注入④ 怕闭包钉住作用域泄漏闭包持有整个作用域链长期存活回调捕获大对象会滞留内存传参写法对照// 用第三参数喂数据效果等价于闭包版但更啰嗦setTimeout((cli,dir)cli.call(checkUpgrade,{directory:dir}),1000,client,cwd)取舍准则汇总维度用闭包必须传参变量可见性在回调定义作用域内在作用域外取值时机执行时实时读取注册时固化快照回调形态一次性内联独立复用/可传递生命周期无长引用顾虑怕闭包钉住大作用域一句话记忆变量在作用域内 要实时值 一次性内联 → 闭包变量在作用域外 要值快照 回调要复用/传递 怕长引用泄漏 → 传参。200 篇的setTimeout回调四个条件全满足闭包所以写成() client.call(...)而非setTimeout(fn, 0, args)。OK本篇先到这里如有疑问欢迎评论区留言讨论祝各位功力大涨技术更上一层楼更多内容见下篇 blog