(debounce)防抖 :
在一段时间内 控制事件触发一次 。如果在时间内触发 那么会重新计时 过完时间后在可以触发;
前置防抖
<button class="btn1">点击前置防抖</button>
<button class="btn3">点击前置防抖2</button>
<button class="btn2">点击后置防抖</button>
<input type="text" class="myinput" />
先执行函数 在防抖
let timer = null;
document.querySelector(".btn1").onclick = function () {
// console.log(timer);
if (!timer) {
console.log(1111);
}
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
}, 1000);
}
提取防抖逻辑 写一个通用函数 ,提高复用性;
document.querySelector(".btn1").onclick = debounce(function () {
console.log(111, this);
}, 1000);
document.querySelector(".btn3").onclick = debounce(function () {
console.log(3333);
}, 2000);
function debounce(fn, delay) {
let timer = null;
return function () {
// console.log(this);
if (!timer) {
// fn();
// fn.call(this);
fn.apply(this, arguments);
}
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
}, delay);
}
}
后置防抖
先防抖 在执行函数
let timer2 = null; // 变量污染 ;
document.querySelector(".btn2").onclick = function () {
// console.log(timer);
clearTimeout(timer2);
timer2 = setTimeout(() => {
timer2 = null;
console.log(2222);
}, 1000);
}
document.querySelector(".btn2").onclick = debounce2(function () {
console.log("后置防抖");
}, 2000);
function debounce2(fn, delay) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
// console.log(2222);
fn.apply(this, arguments);
}, delay);
}
}
(trottle)节流
控制事件执行的频率 ,在一段时间内重复执行;
let startTime = new Date().getTime(); //时间戳
document.onmousemove = function () {
let nowTime = new Date().getTime();
if ((nowTime - startTime) > 500) {
console.log(11111);
startTime = new Date().getTime();
}
}
document.onmousemove = trottle(function(){
console.log("mousemove")
},1000);
document.querySelector(".myinput").oninput = trottle(function(){
console.log(this.value);
},1000);
// 提取逻辑 写一个 通用的节流函数
function trottle(fn, delay) {
let startTime = new Date().getTime();
return function () {
let nowTime = new Date().getTime();
if ((nowTime - startTime) > delay) {
fn.apply(this,arguments);
startTime = new Date().getTime();
}
}
}
用玩游戏的思路去看待防抖和节流大概就是 :防抖:施法前摇。 节流 :技能的cd。
通用函数中涉及到了一些闭包相关概念,以下对该问题进行简述;
闭包 :函数对于外部环境context(上下文)的引用 ;
var num = 10; // 在内存中不会被销毁;
function test(){
console.log(num);
}
test();
function test(){
var num = 10; //被内存缓存起来
return function(){
num++;
console.log(num)
}
}
// test();
// console.log(num);
let fn = test();
fn();
fn();
fn();
function test(){
console.log("test");
}
// 让test函数只能执行一次;
function once(fn){ // 记录 test的执行状态;
let flag = false;
return function(){
if(!flag){
fn();
flag = true;
}else{
console.log("已经执行过了");
}
}
}
let myfn = once(test);
myfn();
myfn();
myfn();
高阶函数 :有函数作为输入 或者输出的函数 ;
以函数作为输入;也把输入的这个函数叫回调函数 callback
function fn1(fn){
fn();
}
fn1(function(){})
// 以函数作为输出
function fn2(){
var a = 20;
return function(){
console.log(a);
}
}
一个防抖节流的示范
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
height: 3000px;
}
</style>
</head>
<body>
<button>点击</button>
<script>
const oBtn=document.querySelector("button");
// 函数防抖
// let t;
// window.onscroll=function(){
// clearInterval(t);
// t=setInterval(function(){
// console.log(2022);
// clearInterval(t);
// },1000)
// }
// 函数节流 disabled
// oBtn.onclick=function(){
// oBtn.disabled=true;
// let count=3;
// oBtn.innerHTML=count+"s之后可以再次点击";
// let t=setInterval(function(){
// count--;
// oBtn.innerHTML=count+"s之后可以再次点击";
// if(count<=0){
// clearInterval(t);
// oBtn.disabled=false;
// oBtn.innerHTML="点击";
// }
// },1000)
// }
// 函数节流 flag
let flag=true;
oBtn.onclick=function(){
if(flag){
flag=false;
let count=3;
oBtn.innerHTML=count+"s之后可以再次点击";
let t=setInterval(function(){
count--;
oBtn.innerHTML=count+"s之后可以再次点击";
if(count<=0){
clearInterval(t);
flag=true;
oBtn.innerHTML="点击";
}
},1000)
}
}
</script>
</body>
</html>