// 简化实现,完整版实现中的第 2 步
Function.prototype.bind = function (context) {
var self = this;
// 第 1 个参数是指定的 this,截取保存第 1 个之后的参数
// arr.slice(begin); 即 [begin, end]
var args = Array.prototype.slice.call(arguments, 1);
return function () {
// 此时的 arguments 是指 bind 返回的函数调用时接收的参数
// 即 return function 的参数,和上面那个不同
// 类数组转成数组
var bindArgs = Array.prototype.slice.call(arguments);
// 执行函数
return self.apply( context, args.concat(bindArgs) );
}
}
1、以上是bind函数的实现过程
2、高阶函数、函数柯里化
简单来说,高阶函数是一个接受函数作为参数传递或者将函数作为返回值输出的函数。
一个经常用到的柯里化函数:
var curry = function (fn) {
var args = [].slice.call(arguments, 1);
return function() {
var newArgs = args.concat([].slice.call(arguments));
return fn.apply(this, newArgs);
};
};
3、节流
函数节流,指的是在一定的时间间隔内(比如说3秒),只执行一次,在这三秒内无视后来产生的函数调用请求,也不会延长时间间隔。3秒间隔结束后,第一遇到新的函数调用会触发执行,然后在这新的3秒内依旧无视后来产生的函数调用请求,以此类推。
- 应用场景:非常适用于函数被频繁调用的场景,例如:window.onresize事件,mousemove事件,上传进度等等。
- 实现方案一:用时间戳来实现
// fn 是需要执行的函数
// wait 是时间间隔
const throttle = (fn, wait = 50) => {
// 上一次执行 fn 的时间
let previous = 0
// 将 throttle 处理结果当作函数返回
return function(...args) {
// 获取当前时间,转换成时间戳,单位毫秒
let now = +new Date()
// 将当前时间和上一次执行函数的时间进行对比
// 大于等待时间就把 previous 设置为当前时间并执行函数 fn
if (now - previous > wait) {
previous = now
fn.apply(this, args)
}
}
}
// DEMO
// 执行 throttle 函数返回新函数
const betterFn = throttle(() => console.log('fn 函数执行了'), 1000)
// 每 10 毫秒执行一次 betterFn 函数,但是只有时间差大于 1000 时才会执行 fn
setInterval(betterFn, 10)
- 实现方案二:用定时器来实现
//原始函数
function add(a:any, b: any) {
console.log(a + b, '****本身调用', +new Date());
return a + b;
};
//节流函数
const throttle = (fn: any, wait = 50) => {
let timer: any = null;
return (...args: any) => {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, [...args])
timer = null;
}, wait)
}
}
}
// betterFn就是节流之后返回的新函数
const betterFn = throttle(add, 2000);
setInterval(() => {
// 如果在此处直接调用add,会出新add频繁触发的情况,加上throttle之后,明显情况好多了
betterFn(1, 1)
}, 200)
4、防抖
防抖函数debounce指的是某个 函数在某段时间内,无论触发了多少次回调,都只执行最后一次。假如我们设置了一个等待时间3秒的函数,在这3秒内如果遇到函数调用请求就重新计时3秒,直至新的3秒内没有函数请求,此时执行函数,不然就以此类推重新计时。
//防抖
const debounce = (fn: any, wait = 50) => {
let timer: any = null;
return (...args: any) => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
};
};
// betterFn就是防抖之后返回的新函数
const betterFn = debounce(() => console.log('****执行了', +new Date()), 2000);
document.addEventListener('resize', betterFn)