1.什么是闭包:内部函数作用域访问外部函数作用域的变量,内部函数就是闭包。
学习闭包之前先了解一下作用域链。
作用域链:各个作用域的嵌套关系组成一条作用链
作用域链的访问要求:
如果自身作用域声明了该变量,则无需访问作用链,
如果该作用域没有声明该变量,则需要使用该作用域链进行查找。
<script>
var a = 1;
var b = 2;
function fn(x) {
var a = 10;
function bar(x) {
var a = 100;
b = x + a;
return b;
}
bar(20);
bar(200);
}
fn(0);
</script>
知道什么是作用链然后就学习然后看一下闭包的代码
function outterFun(){
let a=10;
function innerFun(){
console.log(a);
}
return innerFun();
}
let fun =outterFun();
fun();
闭包的缺点:内部函数没有执行完成,外部函数的变量不会被销毁。
引用场景:封装一段模块化的代码,防止变量被污染。
2.防抖与节流
防抖:用户触发事件过于频繁,只需要最后一次事件的操作。
应用场景:
- 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
- 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
- 文本编辑器实时保存,当无任何更改操作一秒后进行保存
//防抖实现代码
let inp=document.querySelector('input');
inp.oninput=debounce(function(){
console.log(this)
},500)
function debounce(fn,delay){
let timer=null;
return function(){
if(timer!==null){
clearTimeout(timer);
}
timer=setTimeOut(()=>{
//通过call方法改变了fn的this指向
fn.call(this)
},delay)
}
}
节流:减少一段时间内触发的频率
应用场景:
- scroll 事件,每隔一秒计算一次位置信息等
- 浏览器播放事件,每个一秒计算一次进度信息等
- input 框实时搜索并发送请求展示下拉列表,没隔一秒发送一次请求 (也可做防抖)
<script>
/*
节流
思路:
节流是确保在delay之前只有一次事件触发,因此设立一个标志,如果检测到触发的时间已经设置了定时器,那么此次将不会被执行
如果是第一次或delay之后,那么就会设置flag为flase即同样的时间目前还没有一个等待执行的
*/
function throttle(fun, delay) {
let flag = true;
return function () {
if (!flag) {
return;
}
flag=false;
setTimeout(() => {
fun.apply(this, arguments);
flag = true;
}, delay)
};
}
function output() {
console.log("节流" + Math.random());
}
</script>
区别:两者区别在于函数节流是固定时间做某一件事,比如每隔1秒发一次请求。而函数防抖是在频繁触发后,只执行一次(两者的前提都是频繁触发)