节流
一段时间内只执行一次动作
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的指向问题,牢记以下几点:
- 普通的
function函数,this指向Window,严格模式下指向undefined; - 对象中的方法(不能是箭头函数)中,
this指向该对象; - new 构造函数(不能是箭头函数)中,
this指向实例对象; - HTML 事件函数(不能是箭头函数)中,
this指向了接收事件的 HTML 元素; call,apply,bind可以显示绑定this,指向当前环境的this- 箭头函数没有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。
版权声明:本文为qq_44870156原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。