什么是闭包
- 函数嵌套函数
- 内部函数可以引用外部函数的参数和变量
参数和变量不会被垃圾回收机制所回收
<script>function aaa(b){var a = 10;console.log(a, b);function bbb(){console.log(a,b);}return bbb;}var res = aaa(20);//10 20console.log(res);//ƒ bbb(){console.log(a,b);}(res代表嵌套函数bbb)res();</script>
垃圾回收机制
垃圾回收机制是指函数内部的形参和变量随着函数的调用被创建,随着函数调用结束而被销毁。
闭包的好处
希望一个变量常驻内存当中
避免全局变量污染
//闭包函数的美化,函数声明以后立即调用的写法,叫做立即执行函数。var ccc = (function(){var a = 2;return function(){a++;console.log(a);}})();ccc();ccc();
可以声明私有成员 ```javascript //A同学 var moduleA = (function(){
var count = 0; //私有变量 只能被私有方法访问function showA(){ //私有方法count += 20;console.log(count);}function showB(){count += 10;console.log(count);}return {outA: showA,outB: showB}
})();
moduleA.outA(); moduleA.outB(); // console.log(count);报错 // console.log(showA);报错
//B同学var moduleB = (function(){var count = 1000; //私有变量 只能被私有方法访问function showA(){ //私有方法count += 200;console.log(count);}function showB(){count -= 100;console.log(count);}return {outA: showA,outB: showB}})();moduleB.outA();moduleB.outB();
<a name="3kTp5"></a>## 给每个按钮添加点击```javascript//闭包方法window.onload = function(){var aBtns = document.getElementsByTagName("button");//通过循环给每一个按钮添加点击for(var i = 0; i < aBtns.length; i++){aBtns[i].onclick = (function(index){return function(){alert(index);}})(i);}}<body><button>按钮1</button><button>按钮2</button><button>按钮3</button></body>//this方法window.onload = function(){var aBtns = document.getElementsByTagName("button");//通过循环给每一个按钮添加点击for(var i = 0; i < aBtns.length; i++){aBtns[i].index = this;aBtns[i].onclick = function(){console.log(this.index);}}还有就是把var改为this
启动延时器
for(let i = 0; i < 5; i++){setTimeout(function(){console.log(i);}, 4000);}for(var i = 0; i < 5; i++){setTimeout((function(index){return function(){console.log(index);}})(i), 4000);}
函数的防抖
window.onload = function(){var oBtn = document.getElementById("btn1");var i = 0;function antiShake(funcName, delay){var timer = null;return function(){var argus = [...arguments];var _this = this;clearTimeout(timer);timer = setTimeout(function(){//this指向 参数funcName.apply(_this, argus)}, delay);}}function show(ev){console.log(i++, ev);}show = antiShake(show, 500);oBtn.onclick = show;}////////////function antiShake(funcName, delay){var timer = null;return function(){// var argus = [arguments];// var _this =this;clearTimeout(timer);timer = setTimeout(() =>{funcName();},delay)}}
函数的节流
window.onload = function(){var node = document.getElementById("div1");var i = 0;//函数调用频率太快了 降频率// var timer = null;// node.onmousemove = function(){// if(!timer){// timer = setInterval(function(){// node.innerHTML = i++;// clearInterval(timer);// timer = null;// }, 500);// }// }function show(){node.innerHTML = i++;}show = throttle(show, 2000);node.onmousemove = show;}function throttle(funcName, delay){var timer = null;return function(){var argus = [...arguments];var _this = this;if(!timer){timer = setInterval(function(){funcName.apply(_this, argus);clearInterval(timer);timer = null;}, delay)}}}
闭包的缺点
闭包会导致内存泄漏(由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除)
window.onload = function(){var node = document.getElementById('div1');var id = node.id;//不要在闭包中直接传入对象,借用上面函数的变量,缓解内存泄漏node.onclick = function(){alert(id);}node.onclick = null;//取消闭包node = null;//取消对象}//IE浏览器window.onload = function(){var node = document.getElementById("div1");node.onclick = function(){alert(node.id);}window.onunload = function(){//页面解构的时候执行node.onclick = null;node = null;}}
观察者模式
<script>function Observer(){this.users = [];}Observer.prototype.subscibe = function(user){this.users.push(user);}Observer.prototype.unsubscibe = function(user){this.users = this.users.filter(item => item != user);}//msg 广播的数据Observer.prototype.broadcast = function(msg){//遍历所有的用户,进行广播for(var i in this.users){this.users[i](msg);}}//实战:var kai55 = new Observer();function xiaoming(msg){console.log("您好,您有一条新消息:" + msg + ", 小明说:五五开绝对没有开挂");}function xiaohua(msg){console.log("您好,您有一条新消息:" + msg + ", 小花说:五五真帅");}kai55.subscibe(xiaoming);kai55.subscibe(xiaohua);kai55.broadcast("五五开要开播了,我55开,绝对没有开挂");kai55.unsubscibe(xiaoming);kai55.broadcast("道歉");</script>
