看了别人实现的节流代码,十分不理解这个闭包里this,arguments的含义,望指点一二

function throttle(fn,interval){
var timer,
    isFirst = true;
return function(){
//////////////////////////////////////////////////////////////////////
    var args = arguments,      就是这里了
        that = this;
///////////////////////////////////////////////////////////////////////
    if(isFirst){
        fn.apply(that,args)
        return isFirst = false
    }
    if(timer){
        return
    }
    timer = setTimeout(() => {
        clearTimeout(timer)
        timer = null
        fn.apply(that,args)
    }, interval || 1000);
}   
}
阅读 3.2k
3 个回答

首先你要明白,throttle的功能是接受一个函数并返回一个新的函数,这个函数有节流的功能

用法会是这样:

function handleClick(param) {console.log('clicked', param)};

const throttledHandleClick = throttle(handleClick, 2000)

// 下面的代码只会打印一次clicked
throttledHandleClick('p')
throttledHandleClick('p')
throttledHandleClick('p')

所以你说的arguments其实就是

{
 0 : 'p',
}
如果你不 fn.apply(that,arguments),而是fn() 那么参数就会丢失

关于this,个人感觉this应该取决于生成函数时候的执行方式,throttle(handleClick, 2000), 所以this就是window。 而不是如你写的取决于最终函数throttledHandleClick的调用方式。

如果按照我的理解应该这么写:

function throttle(fn,interval){
    var timer,
        isFirst = true;
        that = this; // 注意这里
return function(){
    if(isFirst){
        fn.apply(that,arguments)
        return isFirst = false
    }
    timer = setTimeout(() => {
        clearTimeout(timer)
        timer = null
        fn.apply(that,arguments)
    }, interval || 1000);
}   
}

arguments 是当前函数被调用时传入的参数,这个是特殊的内建参数,换个方法块它的值就不一样了,所以用 var args = arguments 来拷贝一份当前函数被调用时的参数。

var that = this 同样是拷贝一份当前的上下文,或者说 this 指向。

这两行代码是为了下面定时器内调用所做的一次拷贝,这涉及到 this 指向、作用域等等一系列知识点。

新手上路,请多包涵

这个应该就是习惯性写法。
在这段代码的情形下,并不涉及构造closure造成的context变化,不做这一步转引也一样能正常运行。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题