Skip to content

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