函数式编程:是一个泛指名词,是一种编程思想,面向对象编程也是一种思想;就像“花”也是一个泛指名称,表示的是所有的花类,“玫瑰花”是一个特指名词,表示的是一种的花。
函数的定义:于集合A中任意一个元素,在集合B中都有唯一的元素与之对应;
在JS中:函数是不依赖任何其他对象,独立存在,是封装代码固定逻辑的容器;
在JS中函数可以做的事情:函数声明,赋值、传参、返回、立即执行、创建对象,这个也是函数作为一等公民的原因;
纯函数的定义:相同的输入有相同的输出,不依赖且不影响外部环境,也不产生副作用,副作用:函数的内部执行console.log()就是副作用的一种
1、记忆函数(缓存函数)
目的:已经有结果的计算(http请求),重复就不需要执行函数。
实现案例:
function memory(fn) {
const cache = {}
return function() {
let key = Array.from(arguments).join();
return cache[key] = cache[key] || fn.apply(this, arguments);
}
}
// 阶乘
function factorial(n) {
if (n === 0 || n === 1){
return 1
}
return n * factorial(n-1)
}
// 斐波那契数列
function fibonacci(n) {
if (n===1||n===2){
return 1
}
return fibonacci(n-1) + fibonacci(n-2)
}
let fac=memory(factorial);
let fib=memory(fibonacci);
console.log(fac(8));
console.log(fib(8));
2、debounce防抖函数:在n秒之内不断触发执行,定时器重新计时,回调永远不被执行,触发间隔必须大于n秒回调才能会被执行。
2-1:首次不立即执行,必须等待n秒之后执行回调:
function debounce(callback, delay) {
let T = undefined,
_that = this;
return function() {
clearTimeout(T)
T = setTimeout(callback.bind(_that, ...arguments), delay);
}
}
let obj = {name: "tony"}
function sayHello(arg) {
console.log("Hi,my name is" + this.name);
}
let testDebounce = debounce.call(obj, sayHello, 2000);
2-2:首次立即执行
function debounce(callback, delay, immediate) {
let t = undefined,
_self = this;
var debounce = function() {
clearTimeout(t)
if (immediate) {
immediate = false;
callback.call(_self, ...arguments);
} else {
t = setTimeout(callback.bind(_self, ...arguments), delay)
}
}
return debounce;
}
let obj = { name: "tony" }
function sayHello(arg) {
console.log(arg + this.name);
}
let testDebounce = debounce.call(obj, sayHello, 2000, true);
testDebounce("Hi,my name is ");//输出
testDebounce("Hello,my name is ");//不输出
testDebounce("hei,my name is ")//输出
let testDebounce2 = debounce.call(obj, sayHello, 2000);
testDebounce2("Hi,my name is ");//不输出
testDebounce2("Hello,my name is ");//不输出
testDebounce("hei,my name is ")//输出
3、throttle 节流:在n秒之内,不管触发多少次执行,只执行一次回调。
function throttle(callback, delay) {
let t = null,
_self = this,
begin = new Date().getTime();
return function() {
let cur = new Date().getTime();
if (cur - begin >= delay) {
callback.call(_self, ...arguments)
begin = cur;
} else {
if (!t) {
t = setTimeout(() => {
callback.call(_self, ...arguments)
clearTimeout(t)
}, delay)
}
}
}
}
//每一条都打印
let testThrottle = throttle.call(obj, sayHello, 1000);
let i = 0;
setInterval(() => {
i++;
testThrottle("hei" + i)
}, 1100);
//隔3条打印一次
// let testThrottle = throttle.call(obj, sayHello, 1000);
// let i = 0;
// setInterval(() => {
// i++;
// testThrottle("hei" + i)
// }, 300);
4、组合函数(饲养函数)compose:
解决左倾试调用方法:extr(reverse(toUpcase("hello world"))),提高代码可读性
function compose() {
let ags = Array.from(arguments);
return function(key) {
let result = ags.reduce((pre, next) => next(pre), key);
return result
}
}
function toUpcase(key) {
return key.toUpperCase()
}
function reverse(key) {
return Array.from(key).reverse().join("")
}
function extr(key) {
return key + "!!!!"
}
// let composeFn = compose(toUpcase, reverse, extr);
// let composeFn = compose(compose(toUpcase, reverse), extr);
let composeFn = compose(toUpcase, compose(reverse, extr));
console.log(composeFn("hello world"));
// 左倾
console.log(extr(reverse(toUpcase("hello world"))));
5、中间件函数:
1、通过生成器函数返回一个迭代器;
2、nextDo函数的接受迭代器执行next函数返回值obj对象,value就是要执行的函数;
3、如果obj.done的值取反值为true,执行test1函数,test1函数的参数是一个函数,test1里面的next执行的就是该函数"参数函数"。
4、参数函数执行迭代器下一次迭代,返回的值通过递归调用nextDo函数。
5、直到每一个函数都执行完成,或者被执行函数不执行next,也意味着参数函数不被执行,那么递归结束。
var funs = [];
funs.push(function test1(next) {
console.log('test1');
next()
})
funs.push(function test2(next) {
console.log('test2');
next()
})
funs.push(function tes3t(next) {
console.log('test3');
next()
})
funs.push(function test4(next) {
console.log('test4');
next()
});
// funs = [];
var m = function(fns) {
let iterator;
function init() {
iterator = generator(fns)
nextDo(iterator.next())
}
function* generator(fns) {
for (let obj of fns) {
yield obj
}
}
function nextDo(obj) {
if (!obj.done) {
obj.value(function() {
let nextObj = iterator.next()
nextDo(nextObj)
})
}
}
return {
init
}
}
m(funs).init()