假如你前面都看完了跟到了这里,我只能说你很棒棒,不过我不能不说,这才刚刚开始。前面我们已晓得怎样誊写函数式的顺序了,然则我们还没提到掌握流(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; });