【Javascript】节流、防抖函数中的this指向问题

节流

一段时间内只执行一次动作

function throttle(fn,delay){  //这里是否是箭头函数没有关系
  let timer = null;
  return function(){  //如果这里return箭头函数,则没有this,会向上查找this,找到window
    if(timer) return;
    timer = setTimeout(()=>{  //这里又必须是箭头函数,不然this指向window
      fn.apply(this)
      timer = null
    },delay)
  }
}

防抖

一段时间内只执行最后一次动作

function debounce (fn,delay){
  let timer = null;
  return function(){
      if(timer) clearTimeout(timer);
      timer = setTimeout(()=>{
        fn.apply(this);
      },delay)
  }
}

关于this的指向问题,牢记以下几点:

  1. 普通的function函数,this指向Window,严格模式下指向undefined
  2. 对象中的方法(不能是箭头函数)中,this指向该对象;
  3. new 构造函数(不能是箭头函数)中,this指向实例对象;
  4. HTML 事件函数(不能是箭头函数)中,this 指向了接收事件的 HTML 元素;
  5. callapplybind可以显示绑定this,指向当前环境的this
  6. 箭头函数没有this,会沿着作用域链向上查找this,直到找到为止。他会捕获自己在定义时(不是调用时),外层环境的this

所以以下代码中无法将背景颜色变为blue

const debounce = function (fn,delay){
  let timer = null;
  return (...args)=>{
      if(timer) clearTimeout(timer);
      timer = setTimeout(()=>{
        fn.apply(this,args);
      },delay)
  }
}
c.addEventListener("click",debounce(function(){
        console.log(this);   //Window
        console.log(`防抖+${i++}`);
        this.style.backgroundColor='blue'
      },2000))

解释: debounce执行后,返回(return)一个箭头函数,该箭头函数没有this,会沿着定义时的作用域链向上查找this,找到Window,而定时器的回调函数也是箭头函数,也会向上查找,直到找到Window,所以最终this指向Window

可以改成下面的代码(只为了搞清楚this指向才这样写,实际中不推荐这样写防抖)

 c.addEventListener("click",function(){
        console.log('1',this);  //<div id="c"></div>
        const debounce = (fn,delay)=>{  //将防抖函数定义在事件函数中,
        //则向上查找this就是dom元素了。这里必须写成箭头函数的形式,
        //才会向上查找到dom元素。写成普通函数则this还是指向window
        let timer = null;
        console.log('2',this);  //<div id="c"></div>
        return (...args)=>{
            if(timer) clearTimeout(timer);
            timer = setTimeout(()=>{
              fn.apply(this,args);
            },delay)
        }
      }
  
      debounce(function(){
        console.log('3',this);  //<div id="c"></div>
        console.log(`防抖+${i++}`);
        this.style.backgroundColor='blue'
      },2000)()  //要加括号是因为,这里不是回调函数。
      //回调函数不用加括号会自己执行,但普通函数不行
      })

另外, 不管是对象的方法、事件函数还是构造函数,this的指向只在当前函数中有作用,在嵌套函数中会失效,比如

var person = {
 firstName: "John",
  lastName : "Doe",
  id     : 5566,
  fullName : function(){
    console.log(this);
    function test(){
      console.log('2',this.firstName + " " + this.lastName);  //undefined undefined
    }
    test()
    return this.firstName + " " + this.lastName;
  }
};
console.log('1', person.fullName());  //John Doe

此时,fullName方法中的this指向person对象,test函数中的this还是指向Window,若将test改为箭头函数,则其会向上找到对象中的this

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值