本文翻译自 Chalarangelo30 seconds of code - Adapter 一节,并添加自己的学习笔记
转载请注明

Adapter

call

给定一个关键字和一组数据,在给定一个 context 时调用它们,主要被用于组合。
使用闭包通过调用储存的参数来调用储存的关键字

1
const call = (key, ...args) => context => context[key](...args);

Examples
1
2
3
4
5
6
7
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 ]



Note
连续箭头函数-柯里化(curry)
把接受多个参数的函数变换成接受一个单一参数的函数,并且返回(接受余下的参数而且返回结果的)新函数的技术

也就是说,柯里化后,将第一个参数变量存在函数里面了(闭包),然后本来需要 n 个参数的函数可以变成只需要剩下的(n - 1个)参数就可以调用
传统写法
1
2
let add = (x, y) => x + y;
add(2, 3); // 5


连续箭头函数
1
2
3
4
let add = x => y => x + y;
add(2)(3); // 5
let add2 = add(2); // => function(y) {return 2 + y}
add2(3); // 5


对于 let test = a => b => c => {xxx}
这个函数要被调用 3 次 test(a)(b)(c),前两次调用只是在传递参数,只有最后依次调用才会返回 {xxx} 代码段的返回值,并且在 {xxx} 代码段中可以调用 a, b, c

参考自 多个连续的箭头函数与柯里化

扩展运算符
- 语法
用于函数调用
1
myFunction(...iterableObj);


用于数组字面量
1
2
3
4
5
6
7
const [...iterableObj] = [1, 3, 5, 7, 9];

let a = [...iterableObj, 0, 2, 4, 6, 8]; // [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]

let b = [0, 2, ...iterableObj, 4, 6, 8]; // [0, 2, 1, 3, 5, 7, 9, 4, 6, 8]

let c = [...iterableObj, 0, 2, 4, 5, 6, 8, ...iterableObj]; // [1, 3, 5, 7, 9, 0, 2, 4, 5, 6, 8, 1, 3, 5, 7, 9]


用于对象字面量 (new in ECMAScript; stage 3 draft)
1
let objClone = { ...obj};


- 代替apply
在需要使用数组作为函数的参数的情况下,通常使用 Function.prototype.apply 方法:
1
2
3
function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);


如果使用了ES6的展开运算符,你可以这么写
1
2
3
function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);


参考自 扩展语句- JavaScript | MDN

Promise
ES6原生提供了Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
- Promise.resolve
一般情况下我们都会使用 new Promise() 来创建Promises对象。
静态方法 Promise.resolve(value) 可以认为是 new Promise() 方法的快捷方式。
比如 Promise.resolve(42); 可以认为是以下代码的语法糖。
1
2
3
new Promise(function(resolve){
resolve(42);
});


在这段代码中的 resolve(42); 会让这个Promises对象立即进入确定(即resolved)状态,并将 42 传递给后面then里所指定的 onFulfilled 函数。
方法 Promise.resolve(value); 的返回值也是一个Promises对象,所以我们可以像下面那样接着对其返回值进行 .then 调用。
1
2
3
Promise.resolve(42).then(function(value){
console.log(value);
});


- .then
Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。
比如,异步操作 f1 返回一个Promise对象,它的回调函数 f2 写法如下。
1
(new Promise(f1)).then(f2);


这种写法对于多层嵌套的回调函数尤其方便
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 传统写法
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// ...
});
});
});
});

// Promises的写法
(new Promise(step1))
.then(step2)
.then(step3)
.then(step4);


参考自 JavaScript 标准参考教程(alpha)JavaScript Promise迷你书(中文版)Promise对象

collectInto

将接受数组的函数更改为可变参数函数。
给定一个函数,返回一个闭包,将所有输入收集到一个可接受数组的函数中。

1
const collectInto = fn => (...args) => fn(args);


Examples
1
2
3
4
5
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);


flip

flip 将函数作为一个参数,然后将第一个参数作为最后一个参数。
返回一个包含可变参数输入的闭包,并且在应用其余参数之前将最后一个参数拼接成第一个参数。

1
const flip = fn => (...args) => fn(args.pop(), ...args);


Examples
1
2
3
4
5
6
7
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



Notes
Object.assign()
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象

pipeFunctions

执行从左到右的功能组合。
使用 Array.reduce() 和扩展运算符( ... )来执行从左到右的函数组合。 第一个(最左边的)函数可以接受一个或多个参数; 其余的功能必须是一元的。

1
const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));


Examples
1
2
3
4
const add5 = x => x + 5;
const multiply = (x, y) => x * y;
const multiplyAndAdd5 = pipeFunctions(multiply, add5);
multiplyAndAdd5(5, 2); // 15


promisify

转换异步函数以返回一个 promise
使用柯里化(currying)返回一个函数,返回一个调用原始函数的 Promise 。使用 ...rest 运算符传入所有参数。
Node 8+ ,你可以使用 util.promisify

1
2
3
4
const promisify = func => (...args) =>
new Promise((resolve, reject) =>
func(...args, (err, result) => (err ? reject(err) : resolve(result)))
);


Examples
1
2
const delay = promisify((d, cb) => setTimeout(cb, d));
delay(2000).then(() => console.log('Hi!')); // // Promise resolves after 2s


spreadOver

接受一个可变参数函数并返回一个闭包,该闭包接受一个参数数组映射到该函数的输入。
使用闭包和扩展运算符( ... )将参数数组映射到函数的输入。

1
const spreadOver = fn => argsArr => fn(...argsArr);


Examples
1
2
const arrayMax = spreadOver(Math.max);
arrayMax([1, 2, 3]); // 3