码农之家

你是否理解什么是偏函数

我正在参加「掘金·启航计划」

是什么

JavaScript中的偏函数(Partial Function)是指一个函数,它是由另一个函数通过固定一些参数而得到的,从而产生了一个新的函数。这个新函数的功能和原函数一样,只是在调用时需要传入的参数比原函数更少。

偏函数的作用和优点。

偏函数的作用是创建一个新的函数,该函数固定了原函数的部分参数,使得在调用新函数时只需要提供剩余的参数即可。偏函数的优点在于:

  1. 可以减少重复代码。在某些场景下,多个函数的参数有一些相同的部分,使用偏函数可以将这些共同的部分提取出来,避免在多个函数中重复写相同的代码。
  2. 可以使代码更加模块化。偏函数可以将一个大函数拆分成多个小函数,每个小函数只负责一部分参数的处理,使得代码更加清晰、易于维护。
  3. 可以方便地实现柯里化。偏函数是柯里化的一种特殊形式,它可以为柯里化提供一个简单、快速的实现方式。

举例

假设我们正在编写一个Web应用,其中有多个按钮需要监听click事件。每个按钮的click事件处理函数都需要执行一些相同的操作(例如发送AJAX请求),但也有一些不同的参数需要传递(例如不同的URL)。在这种情况下,我们可以使用偏函数来创建一个新的函数,该函数固定了相同的部分参数(例如发送AJAX请求的函数),并将不同的部分参数(例如URL)作为调用时的参数。这样,我们可以避免在每个按钮的click事件处理函数中重复编写发送AJAX请求的代码。同时,我们也可以将发送AJAX请求的函数作为一个单独的模块,以便在其他地方复用。

假设我们有一个函数roundToTwoDecimals,用于将数字四舍五入到两个小数位。现在我们想要使用这个函数来将一个数组中的所有元素都四舍五入到两个小数位,并将结果保存在一个新的数组中。

我们可以使用Array.prototype.map方法来实现这个功能,如下所示:

function roundToTwoDecimals(num) {
  return Math.round(num * 100) / 100;
}

const numbers = [1.234, 2.345, 3.456];
const roundedNumbers = numbers.map(roundToTwoDecimals);
console.log(roundedNumbers); // 输出[1.23, 2.35, 3.46]

这段代码可以正常工作,但在每次调用map方法时,我们都需要手动传递roundToTwoDecimals函数。如果我们在代码中多次使用这个函数,这会导致代码的重复和冗余。

通过使用偏函数,我们可以将roundToTwoDecimals函数转换为一个新函数,该函数接受一个参数,并将该参数传递给roundToTwoDecimals函数。然后我们可以将这个新函数作为参数传递给map方法,从而简化代码。代码如下所示:

function roundToTwoDecimals(num, precision) {
  precision = 10 ** precision;
  return Math.round(num * precision) / precision;
}

const numbers = [1.234, 2.345, 3.456];
const round = (fn, precision) => (value) => fn(value, precision);
const roundToTwoDecimalsPartial = round(roundToTwoDecimals, 2);
const roundedNumbers = numbers.map(roundToTwoDecimalsPartial);
console.log(roundedNumbers); // 输出[1.23, 2.35, 3.46]

在这个例子中,我们定义了一个round函数,它接受两个参数:一个函数fn和一个精度precisionround函数返回一个新函数,该函数接受一个值value,并将fn函数应用于该值和精度参数。然后,我们使用round函数来创建一个新函数roundToTwoDecimalsPartial,该函数将roundToTwoDecimals函数绑定到精度2上。最后,我们将这个新函数传递给map方法,从而将数组中的每个元素都四舍五入到两个小数位。

面试题

请编写一个函数compose,接受任意数量的函数,并返回一个新函数,该新函数将它们组合成一个新函数,从右到左执行。例如:

const add = (a, b) => a + b;
const double = (x) => x * 2;
const square = (x) => x * x;
const composedFn = compose(square, double, add);
composedFn(1, 2); // 36

这里提供一个基于ES6语法的实现,代码如下:

const compose = (...fns) => {
  return (...args) => {
    return fns.reduceRight((result, fn) => {
      return fn(result);
    }, ...args);
  };
};

这个实现基于函数式编程的思想,通过将多个函数组合成一个新函数,使得代码更加简洁、易于阅读和维护。实现过程如下:

  1. 函数compose接受任意数量的函数fns作为参数,并返回一个新函数。
  2. 这个新函数接受任意数量的参数args作为参数,并将它们传递给最右边的函数。
  3. 新函数使用reduceRight方法从右到左依次执行fns中的函数,将每个函数的结果作为下一个函数的参数,最终返回整个函数链的结果。

这个实现具有一定的公用性,可以用于任意数量的函数组合。例如,假设我们有三个函数adddoublesquare,它们分别表示加法、乘以2和平方运算。我们可以使用compose将它们组合成一个新函数,如下所示:

const add = (a, b) => a + b;
const double = (x) => x * 2;
const square = (x) => x * x;
const composedFn = compose(square, double, add);
console.log(composedFn(1, 2)); // 输出 36

这里,composedFn表示adddoublesquare这三个函数组合起来的新函数。我们调用composedFn(1, 2) 时,先将12作为参数传递给add函数,得到结果3;然后将3作为参数传递给double函数,得到结果6;最后将6作为参数传递给square函数,得到结果36,这就是整个函数链的最终结果。

原文链接:https://juejin.cn/post/7234436390280642617 作者:十七喜欢前端