JS的防抖,节流,柯里化和反柯里化
今天我们来搞一搞节流,防抖,柯里化和反柯里化吧,是不是一看这词就觉得哎哟wc,有点高大上啊。事实上,我们可以在不经意间用过他们但是你却不知道他们叫什么,没关系,相信看了今天的文章你会有一些收获的
节流
首先我们来搞一下节流,啥叫节流,就是将高频率触发事件变成低频率触发事件,举个简单的例子,但我们用window.onscroll滚动事件的时候你会发现滚轮滑动一次可能会触发好多次事件,
代码:
window.onscroll = function(){
console.log("触发")
}
结果:
我只是稍微滑动了一下子而已,就触发了十次,这个触发次数实在是过于频繁,那我们有没有什么方法来解决这个问题呢?
思路:我们可以给一个开关,用定时器控制开关的变化,只有当开关打开时我们才去触发打印。
核心代码:
var bStop = true;
window.onscroll = function() {
if(!bStop){
return;
}
bStop = false;
setTimeout(()=>{
var t = document.documentElement.scrollTop || document.body.scrollTop;
console.log(t);
bStop = true;
},300)
}
原谅我直接给你们把代码放上来了,你们就不用一句一句打了,直接拉下代码去就可以run了,美滋滋啊
适用场景:
1.onscroll()
2.onresize()
3.oninput()
等等
防抖
现在我们再来看一看防抖,简单来说,防抖就是不关心中间过程,只关心最后的结果
例如在滚动时,我们需要获取滚动结束时的位置,此时我们并不关心滚动过程中发生了什么,而仅仅只是想知道结束那一刻的状态,那这个时候我们就可以用到防抖
思路:在执行函数时先清除一个延时器,之后再创建一个延时器,这样每次函数触发都会将上一个延时器清除并且建立下一个延时器,中间过程的延时器根本不会被触发,因为他刚创建好就被清除了,只有最后一个延时器,由于没有人来清除他,所以他会正常执行。
可能我说的不是很透彻,没关系,让我直接上代码好吧,代码还是很简洁清晰的
核心代码:
var timer = null;
window.onscroll = function(){
if(timer){
clearTimeout(timer);
}
timer = setTimeout(()=>{
var t = document.documentElement.scrollTop || document.body.scrollTop;
console.log(t);
},300)
}
柯里化
接着我们来搞一搞柯里化好吧,柯里化是指将使用多个参数的函数转换成一系列使用一个参数的函数的技术(又称为部分求值),
目的:为了缩小适用范围,创建一个针对性更强的函数
特点:
1.提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高针对性。
2.对于一个已有函数,对其约定好其中的某些参数输入,然后生成一个更有好的、更符合业务逻辑的函数。
好处:
1.提高针对性
2.延迟执行(只有在最后一次才执行)
3.固定易变因素
现在我们直接上一个小小的例子,有一个厨师,要做饭,但是他的手下没有把菜买齐,这样,买一份原料,放在厨师厨房,再买一份,放在厨师厨房,等买齐了,叫厨师过来,好了,原料齐了,可以做饭了。这个时候,厨师利用原料,把饭做好。厨师就像一个函数,他有自己的功能(做饭),但是参数(原料)不齐,每次执行这个函数,在参数不齐的情况下,只能返回一个新的函数,这个新的函数已经内置了之前的参数,当参数齐了之后完成他本身的功能。
举一个柯里化的小栗子,假设现在我们要按照柯里化的思想实现 add(1,2,3)(1)(2)(3)(4,5,6)(7,8)() 对里面所有的参数求和
直接上代码好吧
// add 函数柯里化
function add(){
//建立args,利用闭包特性,不断保存arguments
var args = [].slice.call(arguments);
//方法一,新建_add函数实现柯里化
var _add = function(){
if(arguments.length === 0){
//参数为空,对args执行加法
return args.reduce(function(a,b){return a+b});
}else {
//否则,保存参数到args,返回一个函数
[].push.apply(args,arguments);
return _add;
}
}
//返回_add函数
return _add;
思想:
1.当参数的长度不为0时,存储参数,
2.当参数的长度为零时,计算所有参数的和
反柯里化
作用:在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用.
对反柯里化更通俗的解释可以是 函数的借用,是函数能够接受处理其他对象,通过借用泛化、扩大了函数的使用范围。
下面放一个通用的柯里化函数:
var uncurrying= function (fn) {
return function () {
var args=[].slice.call(arguments,1);
return fn.apply(arguments[0],args);
}
};