闭包是词法作用域、函数作为一等公民和垃圾回收机制共同作用的自然结果;当内部函数引用外部变量并逃出定义作用域执行时形成闭包,否则不构成;常见问题包括循环变量捕获异常和内存泄漏。
不是 JavaScript 故意“加”的一个功能,而是词法
作用域
+ 函数作为一等公民 + 垃圾回收机制三者自然碰撞出的结果——它不靠语法关键字声明,而是在你写嵌套函数并返回/传递时,
自动产生
。
为什么
返回另一个
就会形成闭包?
JavaScript 在函数定义时就固定了它的词法作用域(即“它写在哪,就认哪的变量”),而不是调用时才查;
当内部函数被返回或赋值给外部变量(比如
),它仍带着对原始定义环境的引用;
引擎发现这个内部函数还在用
,即使
已执行完、本该销毁局部变量,
也不能被回收——否则
下次调用就会报错或读到
。
这背后没有魔法,只是引擎按规则走:
只要变量还在被活引用,就得留着
。
常见误判:不是所有嵌套函数都是闭包
定义在
里 ≠ 形成闭包;
关键看它是否
真正引用了外部变量
,且该函数
逃出了定义它的作用域去执行
。
上面的
不是闭包。而下面这个是:
闭包最常踩的坑:内存泄漏和循环中变量捕获异常
在
循环里直接给元素绑事件,用
声明的循环变量会被所有闭包共享:
立即学习
“
Java免费学习笔记(深入)
”;
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
解决方式:
改用
(块级作用域,每次迭代新建绑定);
或用立即执行函数包裹:
;
或用
替代
。
长期持有 DOM 引用的闭包(比如事件监听器里存了整个节点),又没手动
,变量就一直无法释放。
闭包本身无害,问题出在「引用没及时断」——它像一根看不见的线,把本该消失的变量拽在内存里。写的时候多问一句:这个变量,我之后真还需要吗?
闭包functionfunctionconst counter = createCounter()countcreateCountercountcounter()undefinedinnerouterfunction outer() {
const x = 1;
function inner() {
console.log('没用x,不算闭包'); // 没引用外部变量
}
return inner;
}innerfunction outer() {
const x = 1;
return function() { console.log(x); }; // 引用了 x,且被返回出去
}forvarfor (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 全部输出 3
}let(function(i) { setTimeout(() => console.log(i), 100); })(i)forEachforremoveEventListener