防抖节流里的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没有正确传递:

相关推荐
lichenyang45310 小时前
从零开始构建 React 文档系统 - 完整实现指南
前端·javascript·react.js
比特森林探险记10 小时前
Hooks、状态管理
前端·javascript·react.js
landonVM10 小时前
Linux 上搭建 Web 服务器
linux·服务器·前端
css趣多多11 小时前
路由全局守卫
前端
AI视觉网奇11 小时前
huggingface-cli 安装笔记2026
前端·笔记
比特森林探险记11 小时前
组件通信 与 ⏳ 生命周期
前端·javascript·vue.js
2301_7925800011 小时前
xuepso
java·服务器·前端
海绵宝龙11 小时前
Vue中nextTick
前端·javascript·vue.js
天生欧皇张狗蛋11 小时前
前端部署path问题
前端
H_z_q240112 小时前
Web前端制作一个评论发布案例
前端·javascript·css