前言
本文是作者学习笔记,欢迎指正。
本文多处知识点涉及
js预编译过程 和 V8引擎的垃圾回收机制
闭包的定义
《你不知道的JavaScript》
当函数可以记住并访问所在的词法作用域时,就产生了闭包。即函数是在当前词法作用域之外执行。
闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。
优缺点?
优点
- 实现封装,属性私有化,防止污染全局变量。
- 保护作用域不被释放,成员变量被缓存起来具有记忆性。
- 模块开发,
缺点
- 闭包会导致作用域链不释放,造成内存泄漏。
因内存调试的几个案例而引发的思考
本案例是用谷歌浏览器-开发者工具中的内存快照进行实验。也使用了nodejs的process模块,发现二者有差别。以谷歌V8引擎为案例
num内存未释放, 闭包!:
let count = (function () {
let num = new Array(5 * 1000 * 1000).fill(0);
function addNum () { num.push(1); }
function getNum () { return num; }
return {
addNum,
getNum
};
})();
num内存未释放 :
let count = (function () {
let num = new Array(5 * 1000 * 1000).fill(0);
function addNum () { num.push(1); }
return function(){
console.log('num引用没有保存到外部!');
}
})();
num内存释放:
let count = (function () {
let num = new Array(5 * 1000 * 1000).fill(0);
return function(){}
})();
num2的内存释放,num1内存没有被释放:
let count = (function () {
let num = new Array(5 * 1000 * 1000).fill(0);
let num2 = new Array(5 * 1000 * 1000).fill(0);
function addNum () { num.push(1); }
return function () { }
})();
总结
- 由上述案例垃圾回收机制的存在,闭包的形成与函数作用域中的的引用关系有关。
- 我理解的闭包为,闭包可以存储函数和该函数所在的词法作用域内相关联的环境变量, 无关的环境仍会被垃圾回收机制清除掉。