01-addEventListener事件监听的传参调用问题

01-addEventListener事件监听的传参调用问题

前端问题小记-01 addEventListener

今天学习手写防抖函数的时候遇到了一个小问题

            //为鼠标移动事件添加防抖函数        box.addEventListener('mousemove', debounce(move, 300))                // 自定义防抖函数        function debounce(fun, delay) {             console.log(this); //window              }            

防抖函数中,当在addEventListener中想调用函数时带参 就应该考虑到一个问题就是this指向 , 此时直接在自定义函数中打印this,发现this指向的为全局的window

            //为鼠标移动事件添加防抖函数        box.addEventListener('mousemove', debounce)                // 自定义防抖函数        function debounce(fun, delay) {             console.log(this); //box                 }            

而防抖函数中,我们需要的this是需要指向调用函数的元素对象的(即上述的this指向)

  • [首先要弄明白他们的区别]
//这里相当于是 调用了debounce函数 然后将运行结果传入 作为参数//此时addEventListener 事件 与debounce函数的执行 没有必然联系  // 所以很多时候会出现 设定的事件还没有触发  就已经将函数debounce中的代码执行了    //函数内this的指向也将继续指向全局的 window ①  box.addEventListener('mousemove', debounce(move, 300)) //直接将debounce函数作为参数传入 ②  box.addEventListener('mousemove', debounce)                             //   <---相当于--->  ③  box.addEventListener('mousemove',function debounce(){              console.log(this) //box     })          

①写法并不适用于传参 当然可以直接使用 ③写法进行参数传递 但是debounce作为可复用的封装函数 明显也是不合适的

很简单的一种解决方案 ---闭包

      box.addEventListener('mousemove', debounce(move, 300))            function debounce(move, 300){             //因为上述事件监听使用的是执行debounce 的返回结果              //所以只要将所有需要的内容 封装到一个函数 就会作为参数返回给addEventListener中             return function(){                  //再尝试在这里调用this                 consoloe.log(this) //box             }      }

这样子想要的效果就达成了-------

补)--------防抖函数

 <style>  #box{      width: 100%;      height: 300px;      font-size: 35px;      line-height: 300px;      text-align: center;      background-color: aqua;    } </style><div id="box">     </div>
var box = document.querySelector('#box');let count = 0;box.addEventListener('mousemove', debounce(move, 300,true))function debounce(fun, delay, immediate) {    // !!!! timeout一定要定义在回调函数外面  let timeout;  return function () {    let context = this;    let args = arguments;    clearTimeout(timeout)    if (immediate) {      let callNow = !timeout;      timeout = setTimeout(() => {        timeout = null;      }, delay);      if (callNow) fun.apply(context, args);    } else {      timeout = setTimeout(function () {        fun.apply(context,args)      }, delay);    }      }  }function move(e){  box.innerHTML = count++;}

带注释版

var box = document.querySelector('#box');let count = 0;function move(e) {  // 修改前  this 指向 window  // console.log(this);  //修改了fun的this指向后  这里的 this 已经指向 box 对象  // console.log(this);  //修改前  e的值为undefind  // console.log(e);    box.innerHTML = count++;}//移动鼠标时会不断的执行move函数// box.addEventListener('mousemove',move)// 自定义防抖函数box.addEventListener('mousemove', debounce(move, 1000,true))// box.addEventListener('mousemove', debounce)// box.onmousemove = debounce(move, 300);//underscore防抖函数// box.addEventListener('mousemove',_.debounce(move,300)) // fun 需要进行防抖的函数 delay 延迟的时间  immediate是否立即指向 (true/false)function debounce(fun, delay, immediate) {  // console.log(immediate);  // immediate为true时会忽略delay的延迟事件   // !!!! timeout一定要定义在回调函数外面  let timeout;    // console.log(this);  // addEventListener接受的第二个参数为函数  所以必须返回一个函数 (形成了闭包)  return function () {    // console.log(this);        let context = this;     //arguments中包含了 事件对象    // console.log(arguments);    let args = arguments;    // console.log(args);    // 函数 fun 在延迟 delay 毫秒后执行     clearTimeout(timeout); //清除计时对象       //判断是否立即执行    if (immediate) {      // console.log(timeout);      //鼠标移动的瞬间 timeout的值为undefined       let callNow = !timeout;      //callNow会在移动的一瞬间变为 true       // console.log(callNow);      timeout = setTimeout(() => {        //将延时器变量置空        timeout = null;      }, delay)      // console.log(timeout);         // 立即执行      if (callNow) fun.apply(context, args);    } else {      //不会立即执行      timeout = setTimeout(function () {        // console.log(args);        //执行fun函数 改变fun执行上下文this的指向          fun.apply(context,args)  //第一个参数 改变fun函数this指向  第二个参数 函数所需要的参数(数组类型)          //  fun();        }, delay);    }         }}

欢迎一起交流

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部