摘要:前面我们已经知道如何书写函数式的程序了,但是我们还没提到控制流异常处理异步操作和状态呢容器容器为函数式编程里普通的变量对象函数提供了一层极其强大的外衣,赋予了它们一些很惊艳的特性按照我们的惯例,先从最简单的容器入手。
如果你前面都看完了跟到了这里,我只能说你很棒棒,不过我不得不说,这才刚刚开始。前面我们已经知道如何书写函数式的程序了,但是我们还没提到控制流(control flow)、异常处理(error handling)、异步操作(asynchronous actions)和状态(state)呢?
容器容器为函数式编程里普通的变量、对象、函数提供了一层极其强大的外衣,赋予了它们一些很惊艳的特性
按照我们的惯例,先从最简单的容器入手。
var Container = function(x) { this.__value = x; } Container.of = function(x) { return new Container(x); };
试着执行以下Container.of(3),看看输出的值。
jQuery $(...) 返回的对象并不是一个原生的 DOM 对象,而是对于原生对象的一种封装,某种意义上就是一个“容器”。
我们接着添加一个map方法
Container.prototype.map = function(f){ return Container.of(f(this.__value)) } Container.of(3) .map(x => x + 1) //=> Container(4) .map(x => "Result is " + x); //=> Container("Result is 4")
这个跟前面我们提到的数组操作的map方法非常类似,数组的map方法返回一个新的数组,Container的map方法返回一个新的Container。
上面的这个具有map方法的容器就是我们接下来要引出来的函子。
Functor(函子)是实现了 map 并遵守一些特定规则的容器类型。
Functor 是一个对于函数调用的抽象,我们赋予容器自己去调用函数的能力。当 map 一个函数时,我们让容器自己来运行这个函数,这样容器就可以自由地选择何时何地如何操作这个函数,以致于拥有惰性求值、错误处理、异步调用等等非常牛掰的特性
接着我们看看牛掰的Functor能为我们做什么
var Maybe = function(x) { this.__value = x; } Maybe.of = function(x) { return new Maybe(x); } Maybe.prototype.isNothing = function() { return (this.__value === null || this.__value === undefined); } Maybe.prototype.map = function(f) { return this.isNothing() ? Maybe.of(null) : Maybe.of(f(this.__value)); } Maybe.of("Malkovich Malkovich").map(match(/a/ig)); //=> Maybe(["a", "a"]) Maybe.of(null).map(match(/a/ig)); //=> Maybe(null),代码并没有报错,我们在对函数调用时,检查了函数是否为空
我们如果不想一值.map .map, 可以用柯里化函数对上面的代码稍微改进一下
var map = curry((f, any_functor_at_all) => any_functor_at_all.map(f));
错误处理
var Left = function(x) { this.__value = x; } var Right = function(x) { this.__value = x; } Left.of = function(x) { return new Left(x); } Right.of = function(x) { return new Right(x); } Left.prototype.map = function(f) { return this; } Right.prototype.map = function(f) { return Right.of(f(this.__value)); }
var getAge = user => user.age ? Right.of(user.age) : Left.of("ERROR!"); getAge({name: "stark", age: "21"}).map(age => "Age is " + age); getAge({name: "stark"}).map(age => "Age is " + age); //Left 会终端机链式调用
最后来看下我们不得不做的IO操作
let readLocalStorage = () => { return window.localStorage; }
机智的改造成纯函数
let readLocalStorage = () => { return () => {window.localStorage}; }
然而并没有什么软用
var IO = function(f) { this.__value = f; } IO.of = function(x) { return new IO(() => x); } IO.prototype.map = function(f) { return new IO(_.compose(f, this.__value)); }
var io_window = new IO(function(){ return window; }); io_window.map(function(win){ return win.innerWidth }); io_window.map(_.prop("location")).map(_.prop("href")).map(split("/")); var $ = function(selector) { return new IO(function(){ return document.querySelectorAll(selector); }); } $("#myDiv").map(head).map(function(div){ return div.innerHTML; });
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82881.html
摘要:首先先祝大家国庆节快乐今天距离为我运营公众号已经一个月了,今天把文章整合一下,希望对大家有帮助,也谢谢朋友的支持,我会继续坚持原创,写更好的文章给大家一视频获取学习资源分享合集二功能篇实现金额的语音播报功能基于模式风格的封装之路炫酷动画跳 showImg(https://segmentfault.com/img/remote/1460000011437678?w=900&h=500);...
摘要:首先先祝大家国庆节快乐今天距离为我运营公众号已经一个月了,今天把文章整合一下,希望对大家有帮助,也谢谢朋友的支持,我会继续坚持原创,写更好的文章给大家一视频获取学习资源分享合集二功能篇实现金额的语音播报功能基于模式风格的封装之路炫酷动画跳 showImg(https://segmentfault.com/img/remote/1460000011437678?w=900&h=500);...
摘要:函数式编程我在网上看了很多关于的函数式编程的教程,不过我感觉很多不是照抄的或者就是故弄玄虚。函数式编程几分钟就完事儿了,简单的让人发指。函数式编程理解这么多就够了,再实用就可以看源码了。 JS函数式编程 我在网上看了很多关于javascript的函数式编程的教程,不过我感觉很多不是照抄的或者就是故弄玄虚。js发展到今天越来越往瑜伽圈的风气发展了,拿腔拿调装13不好好说话,好像你讲的东...
阅读 2129·2021-11-18 10:07
阅读 3506·2021-09-04 16:48
阅读 3214·2019-08-30 15:53
阅读 1234·2019-08-30 12:55
阅读 2453·2019-08-29 15:08
阅读 3149·2019-08-29 15:04
阅读 2878·2019-08-29 14:21
阅读 2906·2019-08-29 11:21