JS笔记-fn.apply、this、防抖函数
JS笔记-fn.apply、this、防抖函数
到底为什么写func.apply(this, arguments)掘金
防抖函数是指,在一定时间间隔内,如果没有重复触发函数,才会执行函数体的代码(防止在很短的时间里多次触发的函数),例如网络请求,input输入,浏览器resize监听等。
以下是防抖函数的一个基本实现,通过闭包将主函数体放在timer计时器里,如果二次调用了func,就会通过clearTimeout取消计时器的后续操作,达到防止函数重复触发的效果。
1  | function debounce(func, delay) {  | 
其中这个func.apply(this, arguments);看上去是触发函数的作用,但this和arguments两个参数是什么作用呢?
在js里,this指向当前作用域,只有在运行时才会明确其指向的对象。通过apply的使用,可以修改当前函数的作用域对象:
1  | var name = 'a', age = 0, type = 'A'  | 
如上述代码所示,fn通过apply成功修改了this指向,输出了obj的内容。
插个题外话,以上代码只能在浏览器中运行,如果放在node环境里直接调用fn()只会输出三个undefined。那这个this到底指向哪里了呢?
在浏览器或 Node.js 的全局作用域中,this 都默认指向全局对象。浏览器中的对象是 window,而Node.js 中是 global。与let和const不同,var 声明的变量会成为 window 的属性,因此 this.name 可以访问到值。在浏览器里通过var声明的全局变量是可以通过window直接拿到的:
1  | var name1 = "name1";  | 
但在node环境里,var 变量属于模块作用域,不会挂载到 global 对象,因此全局环境下 this.name1 始终为 undefined:
1  | var name1 = "name1";  | 
明白了this的作用,就很明确func.apply(this, arguments)的使用了。
除了apply()方法外,call()方法也与其类似,但在传参上略有不同。call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
还有一个bind()方法,不同的是此方法会创建一个新的函数,需要重新调用。(bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。)
1  | var name = 'a', age = 0, type = 'A'  | 
理解了以上知识后,我们再回到防抖函数,观察一下是怎么调用的:
1  | const obj = {  | 
我们在调用时传入了一个作用域,这个作用域是如何传入fn函数里的呢?原理就在这句回调函数里:
1  | timer = setTimeout(()=>{  | 
setTimeout里的回调函数会自动继承父级的作用域,也就是testDebounce的作用域。我们通过call()修改了作用域,也就成功实现了作用域传递。





