防抖节流里的this传递

今天心血来潮重写防抖节流,写着写着突然冒出一个问题,为什么执行函数的时候要用apply呢,为什么不直接写fn(...args)呢?

js 复制代码
        //防抖
        function debounce(fn, wait, immediate = false) {
            let timer = null;

            return function (...args) {
                if (immediate && timer === null) {
                    fn.apply(this, args);
                }

                clearTimeout(timer);
                timer = setTimeout(() => {
                    timer = null;
                    if (!immediate) {
                        fn.apply(this, args);  //为什么要用apply?
                    }
                }, wait)
            }
        }
        
        let a = 1;
        function onClick() {
            console.log(this)
            console.log(a++)
        }
        document.addEventListener('click', debounce(onClick, 1000, true))

虽然关于this的指向也背的七七八八,但不得不说,在真实的开发中,有时候还是会被绕进去。那么今天就来扫荡一下迷雾吧。

首先,在这个例子当中,给document绑定了一个click事件,事件处理函数是debounce(onClick, 1000, true),也就是防抖函数这个高阶函数的返回值。

如果这里没有防抖,而是直接这样写:

js 复制代码
document.addEventListener('click', debounce(onClick, 1000, true))

那么onClick内部的this会指向谁呢?答案是指向document。因为浏览器的事件绑定机制是,在哪个元素上绑定了事件函数,该函数的this就指向这个元素。相当于浏览器执行了onClick.call(document, event)。

经过debounce包装了onClick后,它内部的this应该与没包装的时候一样,指向document。

但是,现在onClick与document之间的直接联系已经被切断了,相当于之前是手拉手,现在中间硬插了一个人进来:

js 复制代码
// document--onClick  之前
// document--debounce--onClick  现在

于是,我们就只能通过插入的这个人来进行一个传递。现在,事件处理函数从onClick变成了debounce(onClick, 1000, true),而后者就等同于debounce函数返回的那个函数,因此这个返回函数的this指向了document:

所以现在事情就好办了,只需要在这个返回函数里面调用fn的时候,把this指向传递进去就可以了。可以用apply,也可以用call。而如果不这样做的话,就会出现下图的情况,this没有正确传递:

相关推荐
用户4099322502122 小时前
Vue3中动态样式数组的后项覆盖规则如何与计算属性结合实现复杂状态样式管理?
前端·ai编程·trae
山璞2 小时前
Flutter3.32 中使用 webview4.13 与 vue3 项目的 h5 页面通信,以及如何调试
前端·flutter
努力早日退休2 小时前
Antd Image标签父元素会比图片本身高几个像素的原因
前端
林希_Rachel_傻希希2 小时前
手写Promise--教学版本
前端·javascript·面试
ETA82 小时前
`console.log([1,2,3].map(parseInt))` 深入理解 JavaScript 中的高阶函数与类型机制
前端·javascript
呼叫69452 小时前
图片列表滚动掉帧的原因分析与解决方案
前端
狗哥哥2 小时前
AI 驱动前端自动化测试:一套能落地、能协作、能持续的工程化方案
前端·测试
全栈老石2 小时前
别再折腾端口转发了:使用 Cloudflare Tunnel 优雅地分享你的 localhost
前端·后端·全栈
码云之上2 小时前
WEB端小屏切换纯CSS实现
前端·css