【30秒一個知識點】Adapter

本系列翻譯自開源項目 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]

推薦閱讀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章