前端节流和防抖(上)

节流和防抖(上)

节流和防抖,共性都是对短时间会大量触发浏览器事件的优化

防抖

 //防抖debounce
    /* 在用户触发事件的时间间隔小于(规定时间段)时候才触发函数
        简单来说,就是用户只要触发事件时间比设定的时间段短,那函数就不会触发
        个人粗鄙理解(只要我动得够快,你就不会触发)
    */
<input class="inp" type="text" />
//应用场景,我要在用户输入停止1s后,才打印输出用户的输入内容
    // 防抖函数 (第一版,简易版)
    function debounce(fn, delay) {
        let timer = null;
        return function () {
            // 如果timer存在,清除
            if (timer) {
                clearTimeout(timer)
            }
            // 开规定事件的定时器
            timer = setTimeout(() => {
                fn();
            }, delay)
        }
    }
	
	//获取元素
	let input = document.querySelector('.inp');
	//展示
	 function showVal() {
        console.log('input .value', input .value);
    }
	
	//绑定事件
	input.oninput = debounce(showVal, 1000);
但是简易版中,使用this的时候就会有问题
 function showVal() {
        console.log('this.value', this.value); //输出undefined
    }
//原因在于在闭包返回函数后,this已经指向了window

//解决方法
    // 防抖函数 (第二版,修正this版)
    function debounce(fn, delay) {
        let timer = null;
        return function () {
        		
        	//1.在这里保存函数执行的上下文环境
        	const content = this;
        	
            // 如果timer存在,清除
            if (timer) {
                clearTimeout(timer)
            }
            // 开规定事件的定时器
            timer = setTimeout(() => {
            
            //2.在这里改变函数执行的上下文环境
                fn.call(this);
            }, delay)
        }
    }
在第二版中,我们修正了this,但是对于事件参数并没有修正
 function showVal(e) {
        console.log(e.target);
    }

使用第二部的代码执行上面函数时候会报错
在这里插入图片描述

这个时候就需要第三版

    // 防抖函数 (第三版,修正event参数)
    function debounce(fn, delay) {
        let timer = null;
        return function () {
        		
        	
        	const content = this;
        	//1.在这里保存函数的参数列表
        	const args = arguments;
        	
            // 如果timer存在,清除
            if (timer) {
                clearTimeout(timer)
            }
            // 开规定事件的定时器
            timer = setTimeout(() => {
            
            //2.在这里把函数的参数列表作为参数传递进去
                fn.apply(this,args);
            }, delay)
        }
    }
在这里就会有同学问了,为什么在第三版用apply,不用call呢?

我们可以输出arguments看一下=_=
在这里插入图片描述
很明显arguments是一个参数列表

//函数call和apply都是改变函数的指向,但是参数的传递不一样
fn.call(content,param1,param2...)
fn.apply(conent,[param1,param2...])
//两者的第一个参数都是函数执行的上下文环境,但是后面call是一个个的参数传递,apply是一个参数列表的形势传递

//第三部 使用call传递也是可以的
 fn.apply(this,...args); //使用es6 的...语法将参数列表解构出来

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值