一、闭包的概念和理解
闭包就是在一个内层函数中访问到其外层函数的作用域
在
JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁
示例代码
function fn() { let name = 'zs'; function getName() { // 此时就形成了闭包,在内层函数中访问到外层函数的作用域 alert(name); } getName(); } fn();
二、闭包的使用场景
1.回调
定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。
利用了闭包的特性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <a href="#" id="size-16">16</a> <a href="#" id="size-30">30</a> <a href="#" id="size-40">40</a> <script> function changeFontSize(size) { return function () { document.body.style.fontSize = size + 'px'; }; } // 返回的size12,size14,size16都是函数 var size16 = changeFontSize(16); var size30 = changeFontSize(30); var size40 = changeFontSize(40); // 分别绑定点击事件 document.getElementById('size-16').onclick = size16; document.getElementById('size-30').onclick = size30; document.getElementById('size-40').onclick = size40; </script> </body> </html>
2.setTimeout回调函数传参
setTimeout的第一个参数是执行回调函数,第二个参数是延时时间
原生的setTimeou传递的第一个函数不能带参数,通过闭包可以实现传参效果
以下示例一秒后输出1
function fn1(x) { return function fn2() { console.log(x); }; } let fn = fn1(1); setTimeout(fn, 1000);
3.防抖节流函数的应用(详情见以下链接)
防抖函数
JS防抖函数的实现(巨详细,秒懂)_~black-的博客-CSDN博客
在一定的时间间隔内,如果没有再次触发该函数,那么才会去执行函数体内的代码(例如发送网络请求)。
https://blog.csdn.net/qq_63299825/article/details/130862307
节流函数
JS 节流函数的实现_~black-的博客-CSDN博客
限制一个函数在一定时间内只能执行一次我自己的理解: 节流函数就是 在规定时间内 不管触发几次该事件,都只执行第一次,第一次触发事件等待delay后,事件执行。timer置为null,再次循环。
https://blog.csdn.net/qq_63299825/article/details/130871293
4.柯里化函数
把接受多个参数的函数转换成接受一个单一参数的函数, 当多个参数中 有参数相等时,就实现了闭包和重用的效果。
代码示例如下:
function getArea(width, height) { return width * height; } const area1 = getArea(10, 20); const area2 = getArea(10, 30); const area3 = getArea(10, 40); // 通过上面代码可以发现,第一个参数宽度width都相等。不难发现,可以利用柯里化函数就是 优化 function getArea(width) { return (height) => { return width * height; }; } // 通过调用getArea(10)就返回了 宽度width为10的函数,再次调用传入高度height即可得到面积 const getWidthArea = getArea(10); const area1 = getWidthArea(20); const area2 = getWidthArea(30); const area3 = getWidthArea(40);
5.创建私有变量(JavaScript中声明私有变量的关键字,可以利用闭包的特性声明 私有变量)
每次调用其中一个increase()时,通过改变这个变量的值,会改变这个闭包的词法环境,不会影响另一个闭包中的变量
function fn() { var sum = 0; return { increase() { sum++; return sum; }, }; } let result1 = fn(); console.log(result1.increase()); //1 console.log(result1.increase()); //2 console.log(result1.increase()); //3 // result2 和 result2 的作用域互不影响,和 result2使用的sum互不影响即私有变量sum,result1 let result2 = fn(); console.log(result2.increase()); //1
三、闭包的优缺点
优点:1:变量长期驻扎在内存中,可以重复使用变量
2:闭包可以实现局部变量,避免全局变量的污染
3:可用于声明私有函数和变量
缺点:1.滥用闭包会造成内存泄露
2.性能损失大