本系列翻译自开源项目 30-seconds-of-code 这是一个非常优秀的系列,文章总结了大量的使用 es6 语法实现的代码模块不是说真的三十秒就能理解,也需要你认真的思考,其中有一些点非常精妙,很值得一读。
本文在我的 github 同步更新,你可以看到当前翻译的全部系列。
如果您对本期有不同或者更好的见解,请在下方评论告,喜欢请点个赞,谢谢阅读。
ary
创建一个可以接收 n 个参数的函数, 忽略其他额外的参数。
调用提供的函数 fn, 参数最多为 n 个, 使用 Array.prototype.slice(0,n) 和展开操作符 (…)。
const ary = (fn, n) => (…args) => fn(…args.slice(0, n));
示例
const firstTwoMax = ary(Math.max, 2);
[[2, 6, ‘a’], [8, 4, 6], [10]].map(x => firstTwoMax(…x)); // [6, 8, 10]
call
给定一个 key 和一组参数,给定一个上下文时调用它们。主要用于合并。
使用闭包调用上下文中 key 对应的值,即带有存储参数的函数。
const call = (key, …args) => context => context[key](…args);
示例
Promise.resolve([1, 2, 3])
.then(call(‘map’, x => 2 * x))
.then(console.log); // [2, 4, 6]
const map = call.bind(null, ‘map’);
Promise.resolve([1, 2, 3])
.then(map(x => 2 * x))
.then(console.log); // [2, 4, 6]
collectInto
将一个接收数组参数的函数改变为可变参数的函数。
给定一个函数,返回一个闭包,该闭包将所有输入收集到一个数组接受函数中。
const collectInto = fn => (…args) => fn(args);
示例
const Pall = collectInto(Promise.all.bind(Promise));
let p1 = Promise.resolve(1);
let p2 = Promise.resolve(2);
let p3 = new Promise(resolve => setTimeout(resolve, 2000, 3));
Pall(p1, p2, p3).then(console.log); // [1, 2, 3] (after about 2 seconds)
flip
Flip 以一个函数作为参数,然后把第一个参数作为最后一个参数。
返回一个可变参数的闭包,在应用其他参数前,先把第一个以外的其他参数作为第一个参数。
const flip = fn => (first, …rest) => fn(…rest, first);
示例
let a = {name: ‘John Smith’};
let b = {};
const mergeFrom = flip(Object.assign);
let mergePerson = mergeFrom.bind(null, a);
mergePerson(b); // == b
b = {};
Object.assign(b, a); // == b
over
创建一个函数,这个函数可以调用每一个被传入的并且才有参数的函数,然后返回结果。
使用 Array.prototype.map() 和 Function.prototype.apply()将每个函数应用给定的参数。
const over = (…fns) => (…args) => fns.map(fn => fn.apply(null, args));
示例
const minMax = over(Math.min, Math.max);
minMax(1, 2, 3, 4, 5); // [1,5]
overArgs
创建一个函数,它可以调用提供的被转换参数的函数。
使用 Array.prototype.map()将 transforms 应用于 args,并结合扩展运算符 (…) 将转换后的参数传递给 fn。
const overArgs = (fn, transforms) => (…args) => fn(…args.map((val, i) => transforms[i](val)));
示例
const square = n => n * n;
const double = n => n * 2;
const fn = overArgs((x, y) => [x, y], [square, double]);
fn(9, 3); // [81, 6]
pipeAsyncFunctions
为异步函数执行从左到右的函数组合。
在扩展操作符 (…) 中使用 Array.prototype.reduce() 来使用 Promise.then()执行从左到右的函数组合。这些函数可以返回简单值、Promise 的组合,也可以定义为通过 await 返回的 async 值。所有函数必须是一元的。
const pipeAsyncFunctions = (…fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
示例
const sum = pipeAsyncFunctions(
x => x + 1,
x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)),
x => x + 3,
async x => (await x) + 4
);
(async() => {
console.log(await sum(5)); // 15 (after one second)
})();
pipeFunctions
执行从左到右的函数组合。
在展开操作符 (…) 中使用 Array.prototype.reduce()来执行从左到右的函数组合。第一个 (最左边的) 函数可以接受一个或多个参数; 其余的函数必须是一元的。
const pipeFunctions = (…fns) => fns.reduce((f, g) => (…args) => g(f(…args)));
示例
const add5 = x => x + 5;
const multiply = (x, y) => x * y;
const multiplyAndAdd5 = pipeFunctions(multiply, add5);
multiplyAndAdd5(5, 2); // 15
promisify
把一个异步函数转换成返回 promise 的。
使用局部套用返回一个函数,该函数返回一个调用原始函数的 Promise。使用的 … 操作符来传入所有参数。
const promisify = func => (…args) =>
new Promise((resolve, reject) =>
func(…args, (err, result) => (err ? reject(err) : resolve(result)))
);
示例
const delay = promisify((d, cb) => setTimeout(cb, d));
delay(2000).then(() => console.log(‘Hi!’)); // Promise resolves after 2s
rearg
创建一个调用提供的函数的函数,该函数的参数按照指定的索引排列。
利用 Array.prototype.map() 根据 indexes 和展开操作符 (…) 对参数进行重新排序,将转换后的参数传递给 fn.
const rearg = (fn, indexes) => (…args) => fn(…indexes.map(i => args[i]));
示例
var rearged = rearg(
function(a, b, c) {
return [a, b, c];
},
[2, 0, 1]
);
rearged(‘b’, ‘c’, ‘a’); // [‘a’, ‘b’, ‘c’]
spreadOver
接受一个可变参数函数并返回一个闭包,该闭包接受一个参数数组以映射到函数的输入。
使用闭包和扩展操作符 (…) 将参数数组映射到函数的输入。
const spreadOver = fn => argsArr => fn(…argsArr);
示例
const arrayMax = spreadOver(Math.max);
arrayMax([1, 2, 3]); // 3
unary
创建一个最多接受一个参数的函数,忽略任何其他参数。
只把第一个参数传递给要调用的函数 fn。
const unary = fn => val => fn(val);
示例
[‘6’, ‘8’, ’10’].map(unary(parseInt)); // [6, 8, 10]
推荐阅读
【React 深入】setState 的执行机制
【React 深入】React 事件机制