使用 Ctrl + F or command + F来搜索代码片段
目录
- 🔌 Adapter
- 📚 Array
- chunk(数组分块)
- compact(过滤掉数组中所有假值元素)
- countBy(根据条件对数组分组)
- countOccurrences(计数数组中某个值的出现次数)
- deepFlatten(深度平铺数组)
- difference(数组比较)
- differenceBy(给定条件进行数组比较)
- differenceWith(通过比较函数比较两个数组的差异)
- drop(数组删除)
- dropRight(从右边删除数组)
- dropRightWhile(根据函数从右删除元素)
- dropWhile(根据函数删除元素)
- everyNth( 获得数组中的每个第 n 个元素)
- filterNonUnique(数组去重)
- findLast(获取符合条件的最后一个元素)
- findLastIndex(获取符合条件的最后一个元素索引)
- flatten(平铺数组)
- forEachRight( 从数组的最后一个元素开始遍历数组)
🔌 Adapter
ary(指定函数参数个数)
创建一个函数且接受最多 n 个参数,忽略多余参数。
调用传入的函数 fn 并传入给定的 n 个参数。
参数通过 Array.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 和一个 set 作为参数,给定上下文时调用它们。主要用于函数组合。
使用闭包以存储的参数调用存储的 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.map()和 Function.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.map()与展开操作符(…),通过transforms来转换参数并传递给 fn 。
const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
// 示例
let square = a => a * a;
let doubled = b => 2 * b;
var func = overArgs(
function(x, y) {
return [x, y];
},
[square, doubled]
);
func(9, 3); // [81, 6]
pipeAsyncFunctions(顺序执行异步函数)
从左到右的执行异步函数组合。
使用Array.reduce()与展开操作符(…),从左到右使用Promise.then()执行函数组合。
这些函数可以返回:简单值,Promise的组合或者定义为通过await返回的异步。
所有函数必须是一元函数。
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.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 。
使用柯里化返回一个函数,这个函数返回一个调用原始函数的 Promise 。 使用 …rest 运算符传入所有参数。
在 Node 8+ 中,你可以使用 util.promisify
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(参数重新排列)
创建一个函数调用给定的函数,给定的函数参数按照指定的索引排列。
基于 indexes 使用 Array.reduce() 和 Array.indexOf() 重排参数,使用展开操作符 (…) 向给定函数传参。
const rearg = (fn, indexes) => (...args) =>
fn(
...args.reduce(
(acc, val, i) => ((acc[indexes.indexOf(i)] = val), acc),
Array.from({ length: indexes.length })
)
);
// 示例
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(只接受一个参数的函数)
创建一个最多接受一个参数的函数,忽略任何附加参数。
调用给定函数,只传入第一个参数。
const unary = fn => val => fn(val);
// 示例
['6', '8', '10'].map(unary(parseInt)); // [6, 8, 10]
📚 Array
chunk(数组分块)
把一个数组分块成指定大小的小数组。
使用 Array.from() 创建一个新的数组,它的长度就是生成 chunk(块) 的数量。 使用 Array.slice() 将新数组的每个元素映射到长度为 size 的 chunk 中。 如果原始数组不能均匀分割,最后的 chunk 将包含剩余的元素。
const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
// 示例
chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
compact(过滤掉数组中所有假值元素)
从数组中移除 falsey 值元素。
使用 Array.filter() 过滤掉数组中所有 假值元素(false, null, 0, “”, undefined, 和 NaN)。
const compact = arr => arr.filter(Boolean);
// 示例
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); // [ 1, 2, 3, 'a', 's', 34 ]
countBy(根据条件对数组分组)
根据给定的函数对数组的元素进行分组,并返回每个组中元素的数量。
使用 Array.map() 将数组的值映射到函数或属性名称。 使用Array.reduce() 创建一个对象,其中的键是从映射的结果中产生的。
const countBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});
// 示例
countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2}
countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1}
countOccurrences(计数数组中某个值的出现次数)
计算数组中值的出现次数。
每次遇到数组中的某个特定值时,使用 Array.reduce() 来递增计数器。
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a + 0), 0);
// 示例
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3
deepFlatten(深度平铺数组)
深度平铺一个数组。
使用递归。 通过空数组([]) 使用 Array.concat() ,结合 展开运算符( … ) 来平铺数组。 递归平铺每个数组元素。
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
// 示例
deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]
difference(数组比较)
返回两个数组之间的差异。
根据数组 b 创建一个 Set 对象,然后在数组 a 上使用 Array.filter() 方法,过滤出数组 b 中不包含的值。
const difference = (a, b) => {
const s = new Set(b);
return a.filter(x => !s.has(x));
};
// 示例
difference([1, 2, 3], [1, 2, 4]); // [3]
differenceBy(给定条件进行数组比较)
将给定函数应用于两个数组元素之后,返回两个数组之间的差异。
通过对 b 中的每个元素应用 fn 后创建一个 Set 对象,然后在数组 a 上使用 Array.filter() 和 fn ,只保留之前创建的集合中不包含的值。
const differenceBy = (a, b, fn) => {
const s = new Set(b.map(v => fn(v)));
return a.filter(x => !s.has(fn(x)));
};
// 示例
differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2]
differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ]
differenceWith(通过比较函数比较两个数组的差异)
过滤掉比较函数不返回true的数组中的所有值。
使用 Array.filter() 和 Array.findIndex() 来查找合适的值。
const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
// 示例
differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2]
drop(数组删除)
从左边删除n个元素,并返回新数组。
使用 Array.slice()从左侧删除指定数量的元素。
const drop = (arr, n = 1) => arr.slice(n);
// 示例
drop([1, 2, 3]); // [2,3]
drop([1, 2, 3], 2); // [3]
drop([1, 2, 3], 42); // []
dropRight(从右边删除数组)
从右边边删除n个元素,并返回新数组。
使用 Array.slice()从右侧删除指定数量的元素。
const dropRight = (arr, n = 1) => arr.slice(0, -n);
// 示例
dropRight([1, 2, 3]); // [1,2]
dropRight([1, 2, 3], 2); // [1]
dropRight([1, 2, 3], 42); // []
dropRightWhile(根据函数从右删除元素)
从数组末尾移除元素,直到传递的函数返回true。 返回数组中的其余元素。
循环访问数组,使用Array.slice()删除数组的最后一个元素,直到函数的返回值为true。 返回其余的元素。
const dropRightWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
return arr;
};
// 示例
dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2]
dropWhile(根据函数删除元素)
删除数组中的元素,直到传递的函数返回true。 返回数组中的其余元素。
循环访问数组,使用Array.slice()删除数组的第一个元素,直到函数的返回值为true。 返回其余的元素。
const dropWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
return arr;
};
// 示例
dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4]
everyNth( 获得数组中的每个第 n 个元素)
返回数组中的每个第 n 个元素。
使用 Array.filter() 创建一个包含给定数组的每个第 n 个元素的新数组。
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
// 示例
everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ]
filterNonUnique(数组去重)
过滤掉数组中的重复值。
使用 Array.filter() 滤除掉重复值,使数组仅包含唯一值。
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
// 示例
filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1,3,5]
findLast(获取符合条件的最后一个元素)
返回给定函数返回 true 的最后一个元素。
使用 Array.filter()移除 fn 返回 false的元素,Array.slice(-1)获取最后一个元素。
const findLast = (arr, fn) => arr.filter(fn).slice(-1)[0];
// 示例
findLast([1, 2, 3, 4], n => n % 2 === 1); // 3
findLastIndex(获取符合条件的最后一个元素索引)
返回给定函数返回 true 的最后一个元素的索引。
使用 Array.map() 将每个元素映射到具有索引和值的数组。 使用Array.filter() 移除fn返回 false 的元素,Array.slice(-1) 获取最后一个元素。
const findLastIndex = (arr, fn) =>
arr
.map((val, i) => [i, val])
.filter(val => fn(val[1], val[0], arr))
.slice(-1)[0][0];
// 示例
findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3)
flatten(平铺数组)
使用递归,为每个深度级别 depth 递减 1 。 使用 Array.reduce() 和 Array.concat() 来合并元素或数组。 基本情况下,depth 等于 1 停止递归。 省略第二个参数,depth 只能平铺到 1 (单层平铺) 的深度。
const flatten = (arr, depth = 1) =>
depth != 1
? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flatten(v, depth - 1) : v), [])
: arr.reduce((a, v) => a.concat(v), []);
// 示例
flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
forEachRight( 从数组的最后一个元素开始遍历数组)
从数组的最后一个元素开始,为每个数组元素执行一次提供的函数。
使用 Array.slice(0) 克隆给定的数组,Array.reverse() 反转数组,Array.forEach() 遍历这个反向数组。
const forEachRight = (arr, callback) =>
arr
.slice(0)
.reverse()
.forEach(callback);
// 示例
forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'
未完待续…