什么是闭包,闭包造成的内存泄露如何解决

什么是闭包,闭包造成的内存泄露如何解决

文章目录

1、什么是闭包2、闭包示例代码3、闭包的优缺点4、如何避免闭包引起的内存泄漏5、闭包常见的应用场景1、柯里化函数2、通过闭包实现变量/方法的私有化3、匿名自执行函数4、缓存一些结果

1、什么是闭包

闭包就是一个函数,能够访问其他函数内部变量的函数。 详细来说,闭包就是在一个函数A内部定义一个新的函数B,并且这个新函数B,调用了在函数A内定义的变量,并且在函数A外部被调用,这就形成了闭包。

2、闭包示例代码

function outer() {

var a = '变量1'

var inner = function () {

console.info(a)

}

return inner // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域

}

var inner = outer() // 获得inner闭包函数

inner() //"变量1"

当程序执行完var inner = outer(),其实outer的执行环境并没有被销毁,因为他里面的变量a仍然被inner函数作用域链所引用,当程序执行完inner(), 这时候,inner和outer的执行环境才会被销毁调; 闭包内存泄露的原因:《JavaScript高级编程》书中建议:由于闭包会将它的外部函数的作用域也保存在内存中,因此会比其他函数更占用内存,这样的话,如果过度使用闭包,就会有内存泄露的威胁。

基本类型变量(Number 、Boolean、Undefined、String、Null)的值一般都是存在栈内存中,引用类型变量(Array、Object、Function)的值存储在堆内存中,栈内存存储对应空间地址

3、闭包的优缺点

闭包的优点

访问其他函数内部变量变量长期驻扎在内存中,不会被内存回收机制回收,即延长变量的生命周期;避免定义全局变量所造成的污染

闭包的缺点 大量使用闭包,造成内存占用空间增大,有内存泄露的风险

4、如何避免闭包引起的内存泄漏

1,在退出函数之前,将不使用的局部变量赋值为null;(示例如下)

这段代码会导致内存泄露

window.onload = function(){

var el = document.getElementById("id");

el.onclick = function(){

alert(el.id);

}

}

解决方法为

window.onload = function(){

var el = document.getElementById("id");

var id = el.id; //解除循环引用

el.onclick = function(){

alert(id);

}

el = null; // 将闭包引用的外部函数中活动对象清除

}

2,避免变量的循环赋值和引用。 (示例如上)

循环引用引起的内存泄漏,是因为IE 的bug,循环引用无法自动判断,所以通过拷贝值,把内外引用脱钩,这样就可回收。IE9及其以后已修复。(感谢 猫SirSir 的讲解!)

3,利用Jquery释放自身指定的所有事件处理程序。 由于jQuery考虑到了内存泄漏的潜在危害,所以它会手动释放自己指定的所有事件处理程序。 只要坚持使用jQuery的事件绑定方法,就可以一定程度上避免这种特定的常见原因导致的内存泄漏。

这段代码会导致内存泄露

$(document).ready(function() {

var button = document.getElementById('button-1');

button.onclick = function() {

console.log('hello');

return false;

};

});

当指定单击事件处理程序时,就创建了一个在其封闭的环境中包含button变量的闭包。而且,现在的button也包含一个指向闭包(onclick属性自身)的引用。这样,就导致了在IE中即使离开当前页面也不会释放这个循环。

用jQuery化解引用循环

$(document).ready(function() {

var $button = $('#button-1');

$button.click(function(event) {

event.preventDefault();

console.log('hello');

});

});

5、闭包常见的应用场景

1、柯里化函数

为了避免频繁地调用具有相同参数的函数,可以将一个多参数的函数转化为一个单参数的函数, 其实就是一个高阶函数

//普通函数

function getArea(w,h){

return w * h;

}

const area1 = getArea(10,20);

const area2 = getArea(10,30);

const area3 = getArea(10,40);

//柯里化函数

function getArea(w){

return function(h){

return w * h;

}

}

const getTenArea = getArea(10);

const area1 = getTenArea(20);

const area2 = getTenArea(30);

const area3 = getTenArea(40);

2、通过闭包实现变量/方法的私有化

function funOne(i){

function getTwo(){

console.log('参数:', i)

}

return getTwo;

}

const fa = funOne(100);

const fb = funOne(200);

const fc = funOne(300);

3、匿名自执行函数

var funOne = (function(){

var num = 0;

return function(){

num++;

return num;

}

})()

console.log(funOne()); // 1

console.log(funOne()); // 2

console.log(funOne()); // 3

4、缓存一些结果

比如:外部函数定义一个变量,内部函数可以获取或修改这个变量的值,从而就延长了这个变量的生命周期

function parent(){

let list = [];

function son(i){

list.push(i);

}

return son;

}

const fn = parent();

fn(1);

fn(2);

fn(3);

参考链接: https://blog.csdn.net/liuzijiang1123/article/details/81226797 参考链接:https://www.cnblogs.com/yakun/p/3932026.html 参考链接:https://www.jianshu.com/p/26c81fde22fb


怎么在wps方框里打钩
太赫兹至赫兹转换计算器