JavaScript原始类型在闭包中按值捕获,即捕获定义时的值快照,后续外部变量修改不影响闭包内值;对象类型则捕获引用,可反映外部变更。

JavaScript原始类型在闭包中不会被“引用捕获”,而是按值捕获——每次形成闭包时,会把当时变量的**值快照**存入闭包作用域,后续外部变量变化不影响已捕获的值。
原始类型捕获的是值,不是变量本身
原始类型(string、number、boolean、undefined、null、symbol、bigint)在JS中不可变,且闭包捕获的是其**求值那一刻的副本**,而非对变量内存地址的引用。
例如:
let count = 42; const closure = () => count; count = 99; console.log(closure()); // 输出 42,不是 99
这里 closure 捕获的是 count 在定义时的值 42,之后 count 被重新赋值,对闭包内部无影响。
立即学习“Java免费学习笔记(深入)”;
循环中常见陷阱:for + var vs let
使用 var 声明的循环变量会被提升,所有闭包共享同一个变量绑定;而 let 每次迭代都会创建新绑定,因此捕获的是当次迭代的值。
- var 方式(错误预期):所有函数都捕获到循环结束后的最终值
- let 方式(符合直觉):每个函数捕获各自迭代时的独立值
// var:全部输出 3
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
} // → 3, 3, 3
// let:正确输出 0, 1, 2
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
} // → 0, 1, 2
闭包捕获与重赋值无关,只与定义时求值有关
即使原始类型变量后续被多次修改、甚至重新声明,只要闭包是在某次赋值后定义的,它就固定捕获那个时刻的值。没有“动态跟踪”机制。
注意点:
- 闭包内无法通过任何方式观测外部原始变量后续的变化
- 想实现“响应式”行为,需显式传参、用对象包装,或借助 getter 函数
- 箭头函数和普通函数在此表现一致,区别仅在于
this和arguments绑定
对比对象类型:突显原始类型的“静态性”
对象类型(包括数组、函数、普通对象)在闭包中捕获的是**引用值(即内存地址)**,所以闭包内部可通过该引用读写外部对象的属性——这是原始类型做不到的。
let obj = { x: 1 };
const closureObj = () => obj.x;
obj.x = 99;
console.log(closureObj()); // → 99(可变)
let num = 1;
const closureNum = () => num;
num = 99;
console.log(closureNum()); // → 1(不变)
根本原因:原始类型赋值是拷贝值,对象赋值是拷贝引用;闭包捕获的正是这个“被拷贝的东西”。










