从防抖函数中得到的简单几点记录

一段简单的防抖函数

javascript 复制代码
    const btn = document.querySelector('#btn')
    // 设置初始化timer
    

    function debounce(fn,delay) {
        
        let timer = null
        return function(...args){
            
            
            // 如果timer有值,清除timer
            clearTimeout(timer)
            // 将计时器id给timer
            timer = setTimeout(() => {
                console.log(this); // 有this
                let that = this 
                fn.apply(that,args) 
            }, delay)
        }
    }
    // 每次点击,调用debounce
    btn.addEventListener('click',debounce(function(e) {
        console.log(e);
        console.log(this);//有this
    },1000))

1.闭包在初始化时的调用 timer

less 复制代码
    btn.addEventListener('click',debounce(fn,1000))

此时初始化执行一次debounce(),后续点击事件触发时,执行的是debounce()所返回的函数,所以timer只会在页面加载时初始化一次,后续重新触发debounce()返回的函数时不会重新初始化,这就使得每一次事件都能保留timer的值

2.this的调用

javascript 复制代码
btn.addEventListener('click',debounce(()=>{
console.log(this)//此时是window
},1000))

为什么此时是window呢?因为箭头函数的this由定义时的上下文决定,所以当箭头函数在此时定义时,相当于

javascript 复制代码
const fn = ()=>{console.log(this)}
btn.addEventListener('click',debounce(fn,1000))

这样就能看出来虽然fn被传入了debounce,但是在定义时已经决定了this为window,就算后续fn.apply(that,args) ,也改变不了this的值,所以只能把传入的函数写成普通函数,才能在后续绑定正确的this

3.debonce函数内的fn函数绑定this的问题

javascript 复制代码
    btn.addEventListener('click',debounce(funtion(){
    console.log(this) // 此时this也为window
    },1000))
    
            // 如果timer有值,清除timer
            clearTimeout(timer)
            // 将计时器id给timer
            timer = setTimeout(() => {
                console.log(this); // 有this
                let that = this 
                fn() //在全局调用,此时传入的this为window
            }, delay)

如果fn不显式绑定this,这时候在外层输出的this也为window,因为此时在debounce函数内调用了fn,因为这时候调用的fn(),并没有通过谁来调用,而是在

4.事件对象的传入传出

javascript 复制代码
    btn.addEventListener('click',debounce(function(e) {
        console.log(e);//输出事件对象
        console.log(this);//有this
    },1000))
    
        return function(...args){
            
            
            // 如果timer有值,清除timer
            clearTimeout(timer)
            // 将计时器id给timer
            timer = setTimeout(() => {
                console.log(this); // 有this
                let that = this 
                fn.apply(that,args) 
            }, delay)
        }

由于在事件函数内触发时调用的是debounce返回的函数,所以事件对象也被addEventListener方法给注入进了返回的函数,这时候我们就可以用..args接收,所接收的args则为事件对象所处的数组,再将args通过apply方法传递给我们自己写的fn回调函数,这样就可以在debounce函数外层fn的参数里,得到我们想要的事件对象e

相关推荐
Moment4 分钟前
富文本编辑器技术选型,到底是 Prosemirror 还是 Tiptap 好 ❓❓❓
前端·javascript·面试
xkxnq8 分钟前
第二阶段:Vue 组件化开发(第 18天)
前端·javascript·vue.js
晓得迷路了10 分钟前
栗子前端技术周刊第 112 期 - Rspack 1.7、2025 JS 新星榜单、HTML 状态调查...
前端·javascript·html
怕浪猫13 分钟前
React从入门到出门 第五章 React Router 配置与原理初探
前端·javascript·react.js
鹏多多19 分钟前
前端2025年终总结:借着AI做大做强再创辉煌
前端·javascript
哈__22 分钟前
React Native 鸿蒙跨平台开发:Vibration 实现鸿蒙端设备的震动反馈
javascript·react native·react.js
WebGISer_白茶乌龙桃25 分钟前
Cesium实现“悬浮岛”式,三维立体的行政区划
javascript·vue.js·3d·web3·html5·webgl
不一样的少年_31 分钟前
产品催: 1 天优化 Vue 官网 SEO?我用这个插件半天搞定(不重构 Nuxt)
前端·javascript·vue.js
-dcr33 分钟前
50.智能体
前端·javascript·人工智能·ai·easyui
哈__1 小时前
React Native 鸿蒙跨平台开发:LayoutAnimation 实现鸿蒙端页面切换的淡入淡出过渡动画
javascript·react native·react.js