JavaScript函数的元数
函数的元数是函数期望的参数数量。虽然听起来很理论化,但实际上在实践中非常有用,尤其在函数式编程中。
获取函数的元数
可以使用Function.prototype.length
轻松获取函数的元数。
const arity = fn => fn.length;
arity(Math.sqrt); // 1
arity(Math.pow); // 2
arity((x, y, z) => x + y + z); // 3
arity((...args) => args); // 0
如上面的示例所示,函数的元数是它期望的参数数量。这对于常规函数是正确的,但对于可变参数函数则不是。可变参数函数是接受可变数量参数的函数。在这种情况下,Function.prototype.length
将返回0
。
创建具有固定元数的函数
在某些情况下,我们可能希望限制函数可以接受的参数数量。这对于可变参数函数非常有用,尤其是与柯里化结合使用时。
零元函数的元数
一个零元函数是一个不接受任何参数的函数。在这种情况下,我们可以简单地调用该函数而不传递任何参数。
const nullary = fn => () => fn();
nullary(Math.random)(); // 0.6019623086
一元函数的元数
一个一元函数是一个只接受一个参数的函数,可以通过只提供第一个参数来创建该函数。
const unary = fn => val => fn(val);
['6', '8', '10'].map(unary(Number.parseInt)); // [6, 8, 10]
二元函数的元数
一个二元函数是一个接受两个参数的函数。与一元函数类似,我们可以通过只提供前两个参数来创建一个二元函数。
const binary = fn => (a, b) => fn(a, b);
### N-元函数的元数
一般来说,**n-元函数**是指接受**恰好 `n` 个参数**的函数。使用`Array.prototype.slice()`和扩展运算符(`...`),我们可以创建一个函数,该函数将使用前 `n` 个参数调用提供的函数。
```js
const nAry = (fn, n) => (...args) => fn(...args.slice(0, n));
const firstTwoMax = nAry(Math.max, 2);
[[2, 6, 'a'], [6, 4, 8], [10]].map(x => firstTwoMax(...x)); // [6, 6, 10]
将接受数组参数的函数转换为可变参数函数
在某些情况下,将接受数组参数的函数转换为可变参数函数可能更容易。或者,我们可能希望做相反的操作。使用扩展运算符(...
)和剩余参数,这非常简单。
const toVariadic = fn => (...args) => fn(args);
const fromVariadic = fn => args => fn(...args);
const allPromises = toVariadic(Promise.all.bind(Promise));
let p1 = Promise.resolve(1);
let p2 = Promise.resolve(2);
allPromises(p1, p2).then(console.log); // 输出:[1, 2]
const arrayMax = fromVariadic(Math.max);
arrayMax([1, 2, 3]); // 3