什么是闭包
- 函数嵌套函数
- 内部函数可以引用外部函数的参数和变量
参数和变量不会被垃圾回收机制所回收
<script>
function aaa(b){
var a = 10;
console.log(a, b);
function bbb(){
console.log(a,b);
}
return bbb;
}
var res = aaa(20);//10 20
console.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>