了解 JavaScript 函数式编程 - 代码组合的优势

栏目: JavaScript · 发布时间: 5年前

内容简介:组合函数看起来像是在养植物。你就是养殖员,选择两个有特点又被你喜欢的植物,让它们嫁接(结合)一下,产下一个崭新的品种(函数)。组合的用法如下:就像这样我们把两个函数组合之后返回一个新的函数。

组合函数看起来像是在养植物。你就是养殖员,选择两个有特点又被你喜欢的植物,让它们嫁接(结合)一下,产下一个崭新的品种(函数)。组合的用法如下:

var compose = function(f,g) {
  return function(x) {
    return f(g(x));
  };
};
复制代码

fg 都是函数, x 是在它们之间通过“管道”传输的值。这里得注意一下 compose 函数是组合代码思想中最重要的一环,下面:point_down:会经常用到。大家可以提前 mark 一下

var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '!'; };
var shout = compose(exclaim, toUpperCase);

shout("send in the clowns");
//=> "SEND IN THE CLOWNS!"
复制代码

就像这样我们把两个函数组合之后返回一个新的函数。

对比组合函数

思考一下: 组合的函数和一个完整流程的函数有什么区别

var shout = function(x){
  return exclaim(toUpperCase(x));
};
复制代码

可以看到组合的函数就像乐高玩具一样可以自由的组合成其他的可用的完整的模型乐高建模(完整功能的函数),但是一个像上方一样完整功能,不可拆卸对的函数的。它就像一个已经完成的手办。

了解 JavaScript 函数式编程 - 代码组合的优势 了解 JavaScript 函数式编程 - 代码组合的优势

  • 可以拆解,组合成其他的乐高模型
了解 JavaScript 函数式编程 - 代码组合的优势
  • 不可拆解,出厂的时候已经设计好了。

了解组合代码

让代码从右向左运行,而不是由内而外运行,我觉得可以称之为“左派”(消音~)。我们来看一个顺序很重要的例子:

var head = function(x) { return x[0]; };
var reverse = reduce(function(acc, x){ return [x].concat(acc); }, []);
var last = compose(head, reverse);

last(['jumpkick', 'roundhouse', 'uppercut']);
//=> 'uppercut'
复制代码

上面就是一个反转数组的操作,这里我们看到一个组合函数的执行顺利,我们可以主动的操作函数进行从左到右的方式,但是从右向左的执行顺序更加符合数学上的含义。基本的高中数学知识

// 结合律(associativity)
var associative = compose(f, compose(g, h)) == compose(compose(f, g), h);
// true

compose(toUpperCase, compose(head, reverse));

// 或者
compose(compose(toUpperCase, head), reverse);
复制代码

结合律的好处

结合律的好处是任何一个函数分组都可以被拆解开来,然后再以他们自己的组合打包在一起,组合成新的函数。curry 就是我们的 工具 包。

  • 下面用到了上面 compose 、head、reverse 函数
var loudLastUpper = compose(exclaim, toUpperCase, head, reverse);

// 或
var last = compose(head, reverse);
var loudLastUpper = compose(exclaim, toUpperCase, last);

// 或
var last = compose(head, reverse);
var angry = compose(exclaim, toUpperCase);
var loudLastUpper = compose(angry, last);

// 更多变种...
复制代码

pointfree 空数据模式

pointfree 模式是,no data 模式的意思。这里有一句来自《Love Story》70 年代的电影的台词--“Love means never having to say you're sorry”。

  • 我们的 pointfree 模式就是“Pointfree style means never to say your data”。
  • 下面我们就可以使用柯里化、组合代码中实现以下 pointfree style
// 非 pointfree,因为提到了数据:word
var snakeCase = function (word) {
  return word.toLowerCase().replace(/\s+/ig, '_');
};

// pointfree
var snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);

// 不明白为什么看看最上面的 compose 函数,然后在 控制台试试 snakeCase 函数

snakeCase('Hello World')
// hello_world
复制代码

在 pointfree 版本中,不需要 word 参数就能构造函数;而在非 pointfree 的版本中,必须要有 word 才能进行一切操作。

pointfree 模式能够帮助我们减少不必要的命名,让代码保持简洁和通用。

组合代码的常见问题 debug~

组合的一个常见错误是,在没有局部调用之前,就组合类似 map 这样接受两个参数的函数。

// 下面部分函数来自于上面的 #### 结合律的好处

// 错误做法:我们传给了 `angry` 一个数组,根本不知道最后传给 `map` 的是什么东西。
var latin = compose(map, angry, reverse);

latin(["frog", "eyes"]);
// error


// 正确做法:每个函数都接受一个实际参数。
var latin = compose(map(angry), reverse);

latin(["frog", "eyes"]);
// ["EYES!", "FROG!"])
复制代码

使用 trace(追踪) 来跟踪你的函数

var trace = curry(function(tag, x){
  console.log(tag, x);
  return x;
});

var dasherize = compose(join('-'), toLower, split(' '), replace(/\s{2,}/ig, ' '));

dasherize('The world is a vampire');
// TypeError: Cannot read property 'apply' of undefined

--------------

// 看到报错了,来 trace 一下
var dasherize = compose(join('-'), toLower, trace("after split"), split(' '), replace(/\s{2,}/ig, ' '));
// after split [ 'The', 'world', 'is', 'a', 'vampire' ]

-------------

// tolower 的参数徐亚的是一个数组,所以这里我们 fix 一下我们的代码
var dasherize = compose(join('-'), map(toLower), split(' '), replace(/\s{2,}/ig, ' '));

dasherize('The world is a vampire');

// 'the-world-is-a-vampire'
复制代码

trace 的好处就是可以直接定位到函数调用的地方,允许我们在某个特定的点去观察我们的函数数据

总结

我们可以认为哦组合是高于其他所有原则的设计原则,这是因为组合让我们的代码简单而富有可读性。另外范畴学将在应用架构、模拟副作用和保证正确性方面扮演重要角色。

衍生知识点:一些命名方式

name demo
CamelCase(小驼峰) personId
PascalCase(帕斯卡/大驼峰) PersonId
SnakeCase(下横线) person_id
KebabCase(中横线) person-id

参考


以上所述就是小编给大家介绍的《了解 JavaScript 函数式编程 - 代码组合的优势》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深度学习入门

深度学习入门

[ 日] 斋藤康毅 / 陆宇杰 / 人民邮电出版社 / 2018-7 / 59.00元

本书是深度学习真正意义上的入门书,深入浅出地剖析了深度学习的原理和相关技术。书中使用Python3,尽量不依赖外部库或工具,从基本的数学知识出发,带领读者从零创建一个经典的深度学习网络,使读者在此过程中逐步理解深度学习。书中不仅介绍了深度学习和神经网络的概念、特征等基础知识,对误差反向传播法、卷积神经网络等也有深入讲解,此外还介绍了深度学习相关的实用技巧,自动驾驶、图像生成、强化学习等方面的应用,......一起来看看 《深度学习入门》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具