防抖函数实现中this的指向问题

新手上路,请多包涵

昨天面试的时候让实现一个防抖函数,然后写的如下:

function debounce(fn, delay) {
    var timer; // 维护一个 timer
    return function () {
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(function () {
            fn.apply(this, arguments); 
        }, delay);
        // 正确
        // timer = setTimeout(() => {fn.apply(this, arguments);}, delay);
    };
}

面试官说setTimeout回调里面的那个function需要用箭头函数才没有问题,普通函数和箭头函数的区别在于apply中传入的this和arguments,当时其实没有太理解就照着改了,想求一下这里this指向和argument代指内容的详细的解释,因为我发现网上也有类似的实现,疑惑

阅读 3.5k
3 个回答

箭头函数没有自己的this,也没有自己的arguments,是和上一级的作用域共享this和arguments。

普通的函数声明或者函数表达式,都会在函数体内自动生成this和arguments。

timer = setTimeout(function () {
  // 当前函数体独享的 this
  // 当前函数体独享的 arguments
  fn.apply(this, arguments); 
}, delay);

timer = setTimeout(() => {
  // 查找上一级的 this
  // 查找上一级的 arguments
  fn.apply(this, arguments); 
}, delay);

应为 setTimeout 中的回调函数将被异步执行,导致等到异步调用的时候,this 就指向调用他的上下文了,而不是我们定义上的上下文;

而箭头函数其实并没有this ,可以看一下案例:

// 编译前 箭头函数中的代码
const demo = {
    foo: "apple",
    handler() {
        setTimeout(()=>{
            console.log( this.apple );
        });
    }
}

// 编译后的箭头函数代码
const demo = {
    foo: "apple",
    handler() {
        // 编译之后会自动将 this 转换为中间变量,因此就不存在指针问题
        let _this = this;
        setTimeout(function(){
            console.log( _this.apple );
        });
    }
}

也可以用一下方法解决this指向问题:

const demo = {
    foo: "apple",
    handler() {
        // 将回调函数绑定到当前 this
        setTimeout(function () {
            console.log(this.apple);
        }.bind(this));
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏