# 纯函数、柯里化、偏应用、compose
# 纯函数
给定的输入总是返回相同的输出。 也就是函数的返回只依赖于它的参数 产生可测试的代码, 纯函数不应该改变任何外部环境的变量,函数执行过程没有副作用 合理的代码,必须具有一个有意义的名称, 通过函数名可以轻易的知道函数的作用 js不是一种纯函数语言
// 这个就是纯函数
function priceAfterTax(price) {
return price * 1.2;
}
// 非纯函数 输出依赖外部变量tax
var tax = 0.2;
function priceAfterTax(price) {
return price * (1 + tax);
}
# 柯里化
高阶函数和闭包构成柯里化函数
把一个多参数函数转换为一个嵌套的一元函数的过程
参数顺序
curry函数应用参数列表的顺序应该是从左到右
function curry(fn, ...args) {
return function (...args2) {
return fn(...args, ...args2);
};
}
function sum(a, b, c) {
return a + b + c;
}
const sumWith100 = curry(sum, 100);
console.log(sumWith100(1, 2));
// 参数不定长
function curry2(fn) {
let params = [];
return function anonymous(...args) {
params = [...params, ...args];
if (args.length === 0) {
return fn.apply(null, params);
} else {
return anonymous;
}
};
}
const curry2Sum = curry2(sum);
console.log(curry2Sum(1)(2, 3)());
// 参数定长
function curry3(fn) {
return function anonymous(...args) {
if (args.length < fn.length) {
return function () {
return anonymous(...args, ...arguments);
};
}
return fn(...args);
};
}
# 偏应用(偏函数)
柯里化的参数顺序一般是从左到右, 但有时候我们需要颠倒参数的顺序。
先用一个undefined参数占住位置
// 偏函数
const partial = function (fn, ...partialArgs) {
let args = partialArgs;
// args = [undefined, 1000]
return function (...fullArguments) {
let j = 0;
for (let i = 0; i < args.length && j < fullArguments.length; i++) {
if (args[i] === undefined) {
args[i] = fullArguments[j];
j++;
}
}
return fn.apply(null, args);
};
};
// setTimeout的第一个参数暂时默认设置为undefined
let delayTimMsg = partial(setTimeout, undefined, 10);
delayTimMsg(() => {
console.log('1000s');
});
# compose 函数组合
前一个函数的返回值作为参数传入后面的函数。 比如Redux的中间件就是这个原理
function compose(...funcs) {
return funcs.reduce((a, b) => {
return function (...args) {
return a(b(...args));
};
});
}
function compose2(...funcs) {
return function (...args) {
const funcList = [...funcs];
let result = funcList.pop()(...args);
for (let i = funcList.length - 1; i >= 0; i--) {
result = funcList[i](result);
}
return result;
};
}