Skip to content
On this page

组合


1. 利用 compose 优化处理过程

jsx
let data = parseFloat("3.56");
let number = Math.round(data);
console.log(data);
//3.56
console.log(number);
//4

//! 利用compose将round和parseFloat组合成一个函数,然后执行新函数
let cNumber = compose(Math.round, parseFloat);
let rNumber = cNumber("3.56");
console.log(rNumber);
//4

//! 可以看到通过compose可以使处理过程更简单,使用更加方便

2.无法直接利用compose,通过partial转换后再使用compose

jsx
//获取评分大于4.5的书
let filterGoodBooks = (book) => book.rating[0] > 4.5;
//仅返回书的title和author字段
let projectTitleAndAuthor = (book) => { return { title: book.title, author: book.author } }

//! 由于compose只接受1个参数,所以不能直接组合接收2个参数的filter和map,需要利用partial转化
let queryGoodBooks = partial(filter, undefined, filterGoodBooks);
let mapTitleAndAuthor = partial(map, undefined, projectTitleAndAuthor);

let titleAndAuthorForGoodBooks = compose(mapTitleAndAuthor, queryGoodBooks);
console.log("Good book title and author via compose", titleAndAuthorForGoodBooks(apressBooks))
//Good book title and author via compose [ { title: 'C# 6.0', author: 'ANDREW TROELSEN' } ]

3. 多参函数compose使用

jsx
/**
 * 支持多参数的compose
 * @param  {...any} fns 
 * @returns 
 */
const composeN = function (...fns) {
	return (value) => {
		return reduce(fns.reverse(), (acc, fn) => fn(acc), value);
	}
}

//判断奇偶
let oddOrEven = (ip) => ip % 2 == 0 ? "even" : "odd"

//用空格分割字符串
let splitIntoSpaces = (str) => str.split(" ");

//计算长度
let count = (array) => array.length;

//! 从右往左执行每个函数
var oddOrEvenWords = composeN(oddOrEven, count, splitIntoSpaces);
console.log("Even or odd via pipe ?", oddOrEvenWords("hello your reading about composition"))

var oddOrEvenWordsR = composeN(oddOrEven,composeN(count,splitIntoSpaces));
var oddOrEvenWordsL = composeN(composeN(oddOrEven,count),splitIntoSpaces));

利用compose灵活的组合函数,可以轻松更加复杂的处理函数

4. 管道pipe 实现及应用

类似Unix 的命令执行中的“|”,从左到右处理数据流的过程成为管道。比如:ps -ef | grep nginx

jsx
/**
 * pipe 是compseN的复制品,只是执行顺序是从左至右执行参数函数
 * @param  {...any} fns 
 * @returns 
 */
const pipe = (...fns) => {
	return (value) => {
		return reduce(fns, (acc, fn) => fn(acc), value);
	}
}

//判断奇偶
let oddOrEven = (ip) => ip % 2 == 0 ? "even" : "odd"

//用空格分割字符串
let splitIntoSpaces = (str) => str.split(" ");

//计算长度
let count = (array) => array.length;

//! 从左往执行执行每个函数,每个函数的返回值是下一个函数的参数
let oddOrEvenWords = pipe(splitIntoSpaces, count, oddOrEven);
console.log("Even or odd via pipe ?", oddOrEvenWords("hello your reading about composition"))
//Even or odd via pipe ? 'odd'

5. 利用compose打印中间值,调试复杂的compose函数

jsx
//! 定义调试函数,仅仅打印参数,然后返回参数
const identity = (it) => {
	console.log(it);
	return it
}

//判断奇偶
let oddOrEven = (ip) => ip % 2 == 0 ? "even" : "odd"

//用空格分割字符串
let splitIntoSpaces = (str) => str.split(" ");

//计算长度
let count = (array) => array.length;

//! 需要查看哪个函数处理结果,就将identity放置哪个函数前面(因为:数据是从右往左执行的)
console.log("Debugging", composeN(oddOrEven, count, identity, splitIntoSpaces)("Test string"))

总结

  • pipe和compose做事完全一样,只是处理数据流方向不同而已
  • compose满足结合律

参考文献

以上:如发现有问题,欢迎留言指出,我及时更正

Released under the MIT License.