函数式编程-1

本文探讨了JavaScript中的函数式编程思想,包括函数定义、一等公民特性。重点讲解了记忆化函数、防抖函数、节流函数的实现和应用场景,以及如何使用组合函数提升代码可读性。此外,还介绍了中间件函数的概念,展示了其实现方式。这些技巧在优化性能和控制执行频率方面具有重要意义。
摘要由CSDN通过智能技术生成

函数式编程:是一个泛指名词,是一种编程思想,面向对象编程也是一种思想;就像“花”也是一个泛指名称,表示的是所有的花类,“玫瑰花”是一个特指名词,表示的是一种的花。

函数的定义:于集合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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值