Partial Application(部分应用)是一种编程模式,它可以提高代码的可读性和性能。在 ECMAScript 2017 中,Partial Application 成为了一个标准特性,为前端开发提供了更多实用的方法。
什么是 Partial Application?
Partial Application 是一种将函数的一部分参数固定下来,返回一个新的函数,这个新的函数可以再次被调用并接受另一个参数的函数式编程技术。这个新的函数可以让你在稍后的时间更好地使用原来的函数。举一个简单的例子,下面的代码展示了如何通过 Partial Application 实现 sum 函数:
const sum = (x, y) => x + y; const addToFive = sum.bind(null, 5); console.log(addToFive(3)); // 8 console.log(addToFive(9)); // 14
在这个例子中,我们将 sum 函数绑定到一个值为 5 的参数上,返回了一个新的函数 addToFive,这个函数接受一个新的数值参数,并将其加到 5 上。这样,我们就可以在稍后的时间更方便地使用 sum 函数。
Partial Application 的优势
Partial Application 的主要优势有两点:
1. 可读性
通过使用 Partial Application,我们可以更明确地表达函数的意图。当我们在函数名称中包含一些参数,它们将会更清晰地向调用方传达函数的用途。
2. 性能
将函数的参数绑定到一个固定的值上,可以有效地减少函数调用时的参数传递过程。这样可以优化函数的执行速度,提高代码性能。
如何使用 Partial Application?
在 ECMAScript 2017 中,函数的部分应用可以通过两种方式实现:
1. bind() 方法
我们已经在前面的例子中看到了如何使用 bind() 方法创建一个新的函数。这种方法非常简单,只需要将第一个参数设置为需要固定的值,就可以得到一个新的函数。例如:
const sum = (x, y) => x + y; const addToFive = sum.bind(null, 5); console.log(addToFive(3)); // 8
2. rest 参数
在函数定义中添加一个 rest 参数可以接收任意数量的参数。这允许我们在函数调用时传入任意数量的参数,同时将某些参数固定下来。例如:
const bindFirst = fn => (first, ...rest) => fn.apply(null, [first].concat(rest)); const sum = (x, y) => x + y; const addToFive = bindFirst(sum)(5); console.log(addToFive(3)); // 8
在这个例子中,我们定义了 bindFirst 函数,它接受一个函数 fn 作为参数,并返回一个新的函数。这个新的函数有一个 rest 参数,它可以接收任意数量的额外参数。在这个新函数中,我们将第一个参数先传入 fn,然后将剩余的参数作为数组添加到第一个参数的后面,并使用 apply() 方法调用 fn。这样,我们就得到了一个具有部分应用的函数。
Partial Application 的示例
现在,我们将用 Partial Application 来改进一个常见的场景:使用 Array.map() 和 Array.filter() 方法。
对数组进行部分转换和过滤
假设我们有一个数组来储存人员的信息:
const people = [ { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Charlie', age: 35 }, { name: 'David', age: 20 }, { name: 'Edward', age: 40 } ];
我们想要通过以下条件来过滤这个数组:
- 只包含 30 岁以下的人;
- 只包含名字的长度小于或等于 5 个字符的人;
- 将剩余的人的名字转成大写。
使用 ES5 可以这样实现:
-- -------------------- ---- ------- ----- --------- - ------------------------------ - ------ ---------- - --- --- ----- ---------------- - --------------------------------- - ------ ------------------ -- -- --- ----- ------------------ - ------------------------------------- - ------ - ----- -------------------------- ---- ---------- -- ---
但是这种方法会创建多个中间数组,会导致性能下降。使用 Partial Application 可以让我们实现以下改进:
-- -------------------- ---- ------- ----- ---- - ---------------- - ------ ----------- - ------ ---------------------- -- - ------ ----- -- --- -- -- ----- ------ - ------------ - ------ ------------ - ------ -------------- -- -- ----- --- - ------------ - ------ ------------ - ------ ----------- -- -- ----- ------- - ------------ -------- - ------ --------------------- - ------ ----------- ------------- -- -- ----- --------- - ------------------------------- - ------ ---------- - --- ---- ----- ---------------- - ------------------------------- - ------ ------------------ -- -- ---- ----- ------------------ - -------------------- - ------ - ----- -------------------------- ---- ---------- -- --- ----- -------------- - ----- ---------- ----------------- ------------------ ----------
在这个例子中,我们首先定义了一个 pipe() 函数,它接受任意数量的函数作为输入,并返回一个新的函数,它将接受一个初始值,依次调用所有的函数,并将每个函数的返回值作为下一个函数的输入。
接下来,我们使用 Partial Application 定义了 filter() 和 map() 函数。这些函数返回新的函数,这些函数接受一个数组,并使用传递的函数将数组转换或过滤。
最后,我们使用 Partial Application 定义了三个用来过滤数组的函数 filterAge、filterNameLength、mapNameToUpperCase。这些函数返回一个新的部分应用的函数,可以应用于数组,以满足过滤和映射的特定要求。
最终,我们通过将所有的函数组合到一起,通过 pipe() 函数创建了一个函数,可以从一开始的数组中提取出我们想要的人员信息。
总结
Partial Application 是将函数式编程的思想引入到 ECMAScript 中的有力证据。它可以减少冗余代码和提高程序的性能,同时提高代码的可读性。
使用 Partial Application,我们可以在函数定义的先前设置参数,在以后的时间使用。这使得代码更易于维护和调整,同时保持了代码基本的易于阅读的格式。
在实际开发中,我们可以通过 Partial Application 和其他函数式编程技术来提高代码质量,使用更少的代码执行更多的工作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65b9fad2add4f0e0ff286532