飞码网-免费源码博客分享网站

点击这里给我发消息

函数组成:可维护代码的构件|-JavaScript教程

飞码网-免费源码博客分享网站 爱上飞码网—https://www.codefrees.com— 飞码网-matlab-python-C++ 爱上飞码网—https://www.codefrees.com— 飞码网-免费源码博客分享网站

导体在发光屏幕前的图像

以功能性方式考虑JavaScript的优势之一是能够使用小型,易于理解的单个功能来构建复杂的功能。但是有时,这涉及向后而不是向前看问题,以便弄清楚如何创建最优雅的解决方案。

在本文中,我将采用逐步的方法来检查JavaScript中的功能组合,并演示如何将其生成易于理解且错误较少的代码。

嵌套功能

组合是一种技术,它允许您采用两个或多个简单功能,并将它们组合为一个更复杂的功能,该功能对输入的任何数据按逻辑顺序执行每个子功能。

要获得此结果,请将一个函数嵌套在另一个函数中,然后对内部函数的结果重复执行外部函数的操作,直到产生结果为止。并且结果可能会有所不同,具体取决于功能的应用顺序。

通过将函数调用作为参数传递给另一个函数,可以使用我们在JavaScript中已经很熟悉的编程技术轻松地证明这一点:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

在这种情况下,我们定义了addOne()一个将一个值添加到一个值的timesTwo()函数,以及一个将值乘以2函数。通过将一个函数的结果作为另一个函数的参数传递,我们可以看到,即使在具有相同初始值的情况下,将其中一个嵌套在另一个函数中也可以产生不同的结果。首先执行内部函数,然后将结果传递给外部函数。

势在必行

如果要重复执行相同的操作序列,则定义一个新功能会很方便,该功能会先自动应用一个较小的功能,然后再应用另一个较小的功能。可能看起来像这样:

// ...previous function definitions from above
function addOneTimesTwo(x) {
  var holder = x;
  holder = addOne(holder);
  holder = timesTwo(holder);
  return holder;
}
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10

在这种情况下,我们要做的是按照特定的顺序将这两个函数手动组合在一起。我们创建了一个新函数,该函数首先将要传递的值分配给一个holder变量,然后通过执行第一个函数,然后执行第二个函数来更新该变量的值,最后返回该holder的值。

(请注意,我们正在使用一个名为的变量holder来保存我们暂时传递的值。通过这样一个简单的函数,多余的局部变量可能看起来是多余的,但是即使在命令式JavaScript中,处理参数值也是一个好习惯传递给函数,就好像它们是常量一样。可以在本地修改它们,但是当在函数内的不同阶段调用参数时,会引起混淆。

同样,如果我们想创建另一个新函数,以相反的顺序应用这两个较小的函数,则可以执行以下操作:

// ...previous function definitions from above
function timesTwoAddOne(x) {
  var holder = x;
  holder = timesTwo(holder);
  holder = addOne(holder);
  return holder;
}
console.log(timesTwoAddOne(3)); //7
console.log(timesTwoAddOne(4)); //9

当然,这段代码看起来已经很重复了。我们两个新组成的函数几乎完全相同,除了它们调用的两个较小函数的执行顺序不同。我们需要将其干燥(如“不要重复自己”中的内容)。同样,使用临时变量来像这样改变它们的值不是很有功能,即使它被隐藏在我们正在创建的组合函数内部。

底线:我们可以做得更好。

 

 

创建功能撰写

让我们设计一个组合函数,它可以采用现有函数并将它们按我们想要的顺序组合在一起。为了以一致的方式做到这一点,而不必每次都使用内部函数,我们必须确定要将函数作为参数传递的顺序。

我们有两个选择。每个参数都是函数,它们可以从左到右执行,也可以从右到左执行。也就是说,使用我们提出的新功能compose(timesTwo, addOne)可能意味着timesTwo(addOne())从右到左addOne(timesTwo())读取参数,或者从左到右读取参数。

执行从左到右的参数的优点是,它们将以与英语相同的方式读取,这与我们命名组合函数的方式非常相似,timesTwoAddOne()以暗示乘法应在加法之前进行。我们都知道逻辑命名对于清除可读代码的重要性。

从左到右执行参数的缺点是要操作的值必须先到。但是,将值放在第一位使将来将结果函数与其他函数组合起来不太方便。为了很好地解释这种逻辑背后的思想,您无法击败Brian Lonsdorf的经典视频Hey Underscore,您做错了。(尽管应该注意的是,Underscore现在有一个fp选项,可以帮助解决Brian在将Underscore与lodash-fp或Ramda等功能编程库配合使用时所讨论的功能编程问题。)

 

无论如何,我们真正想做的是先传递所有配置数据,最后传递要操作的值。因此,定义我们的compose函数以读取其自变量并从右至左应用它们是最有意义的。

因此,我们可以创建一个基本compose功能,如下所示:

function compose(f1, f2) {
  return function(value) {
    return f1(f2(value));
  };
}

使用这个非常简单的compose函数,我们可以更简单地构造我们先前的两个复杂函数,并看到结果是相同的:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
function compose(f1, f2) {
  return function(value) {
    return f1(f2(value));
  };
}
var addOneTimesTwo = compose(timesTwo, addOne);
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10
var timesTwoAddOne = compose(addOne, timesTwo);
console.log(timesTwoAddOne(3)); //7
console.log(timesTwoAddOne(4)); //9

尽管此简单compose功能有效,但并未考虑到许多限制其灵活性和适用性的问题。例如,我们可能要组合两个以上的函数。此外,我们this一路走来也无法追踪

我们可以解决这些问题,但是不必掌握合成的工作原理。compose从自己的功能库(例如Ramda)继承更强大的功能,可能比提高自己的功能更有效率,例如Ramda,它默认情况下会考虑参数从右到左的排序。

类型是您的责任

重要的是要记住,程序员有责任了解所组成的每个函数返回的类型,以便下一个函数可以正确地处理它。与执行严格类型检查的纯函数式编程语言不同,JavaScript不会阻止您尝试编写返回不适当类型值的函数。

您不限于传递数字,甚至不限于从一个函数到下一个函数维护相同类型的变量。但是您有责任确保要编写的函数已准备好处理上一个函数返回的任何值。

考虑您的观众

永远记住,将来可能会有其他人需要使用或修改您的代码。对于不熟悉功能范例的程序员来说,在传统的JavaScript代码中使用组合可能显得很复杂。目标是使代码更清晰,更易于阅读和维护。

但是随着ES2015语法的到来,甚至无需compose使用箭头函数的特殊方法就可以将简单的组合函数创建为单行调用

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
var addOneTimesTwo = x => timesTwo(addOne(x));
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10

从今天开始作曲

与所有函数式编程技术一样,请务必牢记所组成的函数应该是纯函数。简而言之,这意味着每次将特定值传递给函数时,该函数应返回相同的结果,并且该函数不应产生会改变其自身外部值的副作用。

当您有一组要应用于数据的相关功能时,组合嵌套会非常方便,并且您可以将该功能的组件分解为可重用且易于组合的功能。

与所有函数式编程技术一样,我建议您明智地将组成部分撒入您现有的代码中以熟悉它。如果操作正确,结果将更整洁,干燥,并使代码更具可读性。那不是我们所有人想要的吗?

飞码网-免费源码博客分享网站 爱上飞码网—https://www.codefrees.com— 飞码网-matlab-python-C++ 爱上飞码网—https://www.codefrees.com— 飞码网-免费源码博客分享网站
赞 ()

相关推荐

内容页底部广告位3
留言与评论(共有 0 条评论)
   
验证码: