闭包
2020-04-27 本文已影响0人
小雪洁
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>闭包</title>
</head>
<body>
</body>
<script>
//子函数可以访问到父级函数的作用域,这种现象称为闭包
let arr=[1,23,4,6,17,3,10,2,5,7,9];
//选出5到9之间的数
let a=arr.filter(function(v){
return v>=5&&v<=9;
});
console.log(a);
//选出3到7之间的数
let b=arr.filter(function(v){
return v>=3&&v<=7;
});
console.log(b);
//考虑函数复用,子函数可以return父级作用域的某些数据,这是闭包的一个很大的特性
function between(a,b){
return function(v){
return v>=a&&v<=b;
}
}
let c=arr.filter(between(2,8));
console.log(c);
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>移动动画的闭包使用</title>
</head>
<style>
button{
position: absolute;
left:0;
}
</style>
<body>
<button>hao</button>
<button>yangdingchuan</button>
</body>
<script>
let btns=document.querySelectorAll('button');
[...btns].forEach(function(item){
let left=1;
let sitid=false;
item.addEventListener('click',function(e){
//问题一、如果left在这里定义,点击第二次时会出现抖动,因为每次点击都会触发使left重新定义
//解决办法是把left放到点击事件外部定义
//let left=1;
//问题二、left放到点击事件外部定义,解决了抖动但是会在每次点击都会加速按钮的移动
//因为每次点击都会重新创建一个定时器,这样点击10次就是创建10个定时器,不是每100ms的速度移动了
//而成了每10ms自增的速度了
/* setInterval(function(){
item.style.left=`${left++}px`;
},100); */
//解决办法:存一个标志,如果定时器已经建立了就不在重复创建了
if(sitid==false){
sitid=true;
setInterval(function(){
item.style.left=`${left++}px`;
},100);
}
});
});
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>利用闭包根据字段排序商品</title>
</head>
<body>
</body>
<script>
let goods=[
{
name:'banana',
price:10,
click:30
},
{
name:'apple',
price:5,
click:40
},
{
name:'grape',
price:15,
click:32
}
];
//按价格升序
let g0=goods.sort(function(a,b){
return a.price>b.price?1:-1;
});
console.log(g0);
//按点击次数降序
let g1=goods.sort(function(a,b){
return a.click<b.click?1:-1;
});
console.log(g1);
//考虑代码复用
function order(field){
return function(a,b){
//升序
return a[field]>b[field]?1:-1;
//降序
//return a[field]<b[field]?1:-1;
}
}
let g2=goods.sort(order("price"));
console.log(g2);
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>闭包的内存泄露解决办法</title>
</head>
<body>
<div name='haoxuejie'>郝雪洁</div>
<div name='yangdingchuan'>杨定川</div>
</body>
<script>
let divs=document.querySelectorAll("div");
/* [...divs].forEach(function(item){
item.addEventListener('click',function(){
console.log(item.getAttribute('name'));
console.log(item);
});
//每次都会在内存中存大量的dom节点,
//如果dom元素内容比较多,会引起内存泄露
}); */
//改进办法
[...divs].forEach(function(item){
let name=item.getAttribute('name');
item.addEventListener('click',function(){
console.log(name);
console.log(item);//null
});
item=null;//及时清理内存,可以使程序运行更快一些
});
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>this在闭包中的历史遗留问题</title>
</head>
<body>
</body>
<script>
let hxj={
user:"haoxuejie",
get:function(){
return this.user;
},
get0:function(){
return function(){
return this.user;
}
},
get1:function(){
return ()=>{
return this.user;
}
}
};
let h=hxj.get();
console.log(h);//haoxuejie
let x=hxj.get0();
console.log(x);//是一个函数
console.log(x());//undefined,因为此时x是全局对象,它的this指向的是window,window里面没有user这个变量
//使用箭头函数解决上述问题,get1()内部定义的返回函数是使用箭头函数定义的
let j=hxj.get1();
console.log(j);//输出一个箭头函数
console.log(j());//haoxuejie
</script>
</html>