闭包:一个可以用自己拥有独立环境与变量的表达式,通常是函数,因为在ES6里已经引入了块级作用域的概念
闭包有三个特性:
函数嵌套函数。
函数内部可以引用外部的参数和变量。
参数和变量不会被垃圾回收机制回收。
闭包的好处:
希望一个变量长期存储在内存中。
避免全局变量的污染。
私有成员的存在。
闭包的缺点:
常驻内存,增加内存使用量。
使用不当会很容易造成内存泄露。
//作为返回值 function fn() { let num = 10; return function() { return num; } } let fnc = fn(); console.log(fnc());
//函数赋值 var fn1; function fn() { let num = 20; fn1 = function() { return num; } } fn(); //赋值 console.log(fn1()); //调用
//函数参数 function fn() { let num = 20; return function callback() { return num; } } //执行函数,将返回值(callback函数)赋值给fn1 let fn1 = fn(); function fn2(f) { //将函数作为参数传入 console.log(f()); //执行函数,并输出 } fn2(fn1);
//IIFE(自执行函数) ( function() { let num = 30; var fn = function() { return num; } //直接在自执行函数里面调用fn2,将fn1作为参数传入 fn1(fn); } )() function fn1(f) { //将函数作为参数传入 console.log(f()); //执行函数,并输出 }
//循环赋值 //每秒执行1次,分别输出1-10 for (let i = 1; i <= 10; i++) { (function(j) { //j来接收 setTimeout(function() { console.log(j); }, j * 1000); })(i) //i作为实参传入 }
//迭代器(执行一次函数往下取一个值) let arr = ['aa', 'bb', 'cc']; function incre(arr) { let i = 0; return function() { //这个函数每次被执行都返回数组arr中 i下标对应的元素 return arr[i++] || '数组值已经遍历完'; } } let next = incre(arr); console.log(next()); //aa console.log(next()); //bb console.log(next()); //cc console.log(next()); //数组值已经遍历完
//缓存 //比如求和操作,如果没有缓存,每次调用都要重复计算,采用缓存已经执行过的去查找,查找到了就直接返回,不需要重新计算 var fn = (function() { var cache = {}; //缓存对象 var calc = function(arr) { //计算函数 var sum = 0; //求和 for (var i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } return function() { var args = Array.prototype.slice.call(arguments, 0); //arguments转换成数组 var key = args.join(","); //将args用逗号连接成字符串 var result, tSum = cache[key]; if (tSum) { //如果缓存有 console.log('从缓存中取:', cache) //打印方便查看 result = tSum; } else { //重新计算,并存入缓存同时赋值给result result = cache[key] = calc(args); console.log('存入缓存:', cache) //打印方便查看 } return result; } })(); fn(1, 2, 3, 4, 5); fn(1, 2, 3, 4, 5); fn(1, 2, 3, 4, 5, 6); fn(1, 2, 3, 4, 5, 8); fn(1, 2, 3, 4, 5, 6);
//防抖 function debounce(callback, time) { var timer; return function() { if (timer) { clearTimeout(timer) } timer = setTimeout(() => { callback() }, time) } }