1.函数柯理化
函数柯理化:预先处理的思想「形成一个不被释放的闭包,把一些信息存储起来,以后基于作用域链,访问到事先存储的信息,然后进行相关的处理,所有符合这种模式(或者闭包应用的)都被称为柯理化函数」
案例:实现求和
function curring(x) {
return function (...args) {
args.unshift(x);
return args.reduce((result, item) => result + item);
};
}
var sum = curring(10);
console.log(sum(20)); //10+20
console.log(sum(20, 30)); //10+20+30
2.关于 curring 函数的应用
实现:
let res = add(1)(2)(3);
console.log(res); //->6
res = add(1, 2, 3)(4);
console.log(res); //->10
res = add(1)(2)(3)(4)(5);
console.log(res); //->15
/*
步骤:
1.编写一个add函数,其参数用剩余运算符传入,其返回值仍然是一个函数
2.在返回的函数中可能还要调用当前函数。
3.进行参数处理:
4.知识点:基于函数进行运算,或者输出的时候,一般都会调用函数的toString。所以我们会在toString做我们的求和操作
*/
let add = function add(...args) {
const proxy = function proxy(...arg) {
args = args.concat(arg);
return proxy;
};
proxy.toString = function () {
return args.reduce((prev, item) => {
return prev + item;
}, 0);
};
return proxy;
};
let res = add(1)(2)(3);
console.log(res); //->6
res = add(1, 2, 3)(4);
console.log(res); //->10
res = add(1)(2)(3)(4)(5);
console.log(res); //->15
--------方案二---------
const curring = function curring() {
let params = [];
const add = function add(...arg) {
params = params.concat(arg);
return add;
};
add.toString = function () {
return params.reduce((prev, item) => {
return prev + item;
}, 0);
};
return add;
};
let add = curring();
let res = add(1)(2)(3);
console.log(res); //->6
add = curring();
res = add(1, 2, 3)(4);
console.log(res); //->10
add = curring();
res = add(1)(2)(3)(4)(5);
console.log(res); //->15
防抖和节流:
-
函数的防抖(debounce)和节流(throttle)
在“高频”触发的场景下,需要进行防抖和节流
-
狂点一个按钮
-
页面滚动
-
输入模糊匹配
-
...
-
-
我们自己设定,多长的时间内,触发两次及以上就算“高频”:封装方法的时候需要指定这个频率(可以设置默认值)
-「防抖」在某一次高频触发下,我们只识别一次(可以控制开始触发,还是最后一次触发);详细:假设我们规定 500MS 触发多次算是高频,只要我们检测到是高频触发了,则在本次频繁操作下(哪怕你操作了 10min)也是只触发一次...
-「节流」在某一次高频触发下,我们不是只识别一次,按照我们设定的间隔时间(自己规定的频率),没到达这个频率都会触发一次;详细:假设我们规定频率是 500MS,我们操作了 10min,触发的次数=(10601000)/500
防抖案例:
let button = document.querySelector(".button");
const debouce = function (func, wait, immdiate) {
//对参数进行处理
if (typeof func !== "function") return;
if (typeof wait !== "number") {
if (typeof wait === "boolean") {
immdiate = wait;
}
}
if (typeof wait === "undefined") {
wait = 500;
}
if (typeof immdiate === "undefined") {
immdiate = false;
}
let timer = null;
return function (...arg) {
let self = this;
let now = immdiate && !timer ? true : false;
console.log(now);
//清除定时器
clearTimeout(timer);
timer = setTimeout(function () {
timer = null;
//执行func的时候确保this是Dom元素,并且闯进去的参数有事件对象
!immdiate ? func.call(self, ...arg) : null;
}, wait);
now ? func.call(self, ...arg) : null;
};
};
button.onclick = debouce(
function () {
console.log("ok");
},
5000,
true
); //true代表点击之后立即执行,false代表疯狂点击的最后一次执行
节流案例:
const throttle = function throttle(func, interval) {
//对参数初始化
if (typeof func !== "function") return;
if (typeof interval === "undefined") {
interval = 500;
}
let pre = 0, //上次触发的时间
timer = null;
return function (...args) {
let now = new Date(),
self = this;
let remaining = interval - (now - pre);
//两次触发的时间间隔大于500ms==》立即执行
if (remaining <= 0) {
clearTimeout(timer);
timer = null; //让下次如果没有超过500能实行定时器
pre = now;
func.call(this, ...args);
} else if (!timer) {
//两次触发时间间隔小于500ms==》
timer = setTimeout(() => {
clearTimeout(timer); //如果间隔小于500ms的等待时间恰好有触发了一次,清除定时器
timer = null;
pre = new Date();
func.call(this, ...args);
}, remaining);
}
};
};
window.onscroll = throttle(function () {
console.log("ok");
}, 5000);