<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
<!-- <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> -->
</head>
<body>
<div class="testDiv">
<h1>编程思想</h1>
<p>
1,函数式编程;
2,面向对象编程(工厂,单例,观察者,发布订阅者等23中设计模式)
3,过程式编程
</p>
<ol>
<li>强调将计算过程分解成可复用的函数</li>
<li>只有纯的、没有副作用的函数,才是合格的函数</li>
<li>函数式编程只是范畴论的运算方法,跟数理逻辑、微积分、行列式是同一类东西,都是数学方法,只是碰巧它能用来写程序。</li>
<li>在函数式编程中,函数就是一个管道(pipe)。这头进去一个值,那头就会出来一个新的值,没有其他作用</li>
<li>没有磁盘读写,或者最大限度的减少磁磁盘读写,纯计算编程</li>
</ol>
<h1>函数式编程有<strong>两个最基本的运算</strong>:合成和柯里化。</h1>
<ol>
<li>如果一个值要经过多个函数,才能变成另外一个值,就可以把所有中间步骤合并成一个函数,这叫做"函数的合成"(compose)。</li>
<li>所谓"柯里化",就是把一个多参数的函数,转化为单参数函数。</li>
<li>
<pre>
var checkage = min => (age => age > min);
var checkage18 = checkage(18);
checkage18(20);
</pre>
</li>
<li>这表明函数柯里化是一种“预加载”函数的能力,通过传递一到两个参数调用函数,就能得到一个记住了这些参数的新函数。从某种意义上来讲,这是一种对参数的缓存,是一种非常高效的编写函数的方法:</li>
<li>
<pre>
// 柯里化之前
function add(x, y) {
return x + y;
}
add(1, 2) // 3
// 柯里化之后
function addX(y) {
return function (x) {
return x + y;
};
}
addX(2)(1) // 3
</pre>
</li>
<li>
<h2>函子概念</h2>
<h3>函数不仅可以用于同一个范畴之中值的转换,还可以用于将一个范畴转成另一个范畴。这就涉及到了函子(Functor)</h3>
<h3>函子是函数式编程里面最重要的数据类型,也是基本的运算单位和功能单位</h3>
<h3>它首先是一种范畴,也就是说,是一个容器,包含了值和变形关系。比较特殊的是,它的变形关系可以依次作用于每一个值,将当前容器变形成另一个容器。</h3>
</li>
<li>
一般约定,函子的标志就是容器具有map方法。该方法将容器里面的每一个值,映射到另一个容器。
</li>
<h1>命令式编程和声明式编程</h1>
<ul>
<li>
<p>命令式代码:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。</p>
<p>声明式代码:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。</p>
<pre>
// 命令式
var makes = [];
for (var i = 0; i < cars.length; i++) {
makes.push(cars[i].make);
}
// 声明式
var makes = cars.map(function(car){ return car.make; });
</pre>
</li>
<li>函数式编程的一个明显的好处就是这种声明式的代码,对于无副作用的纯函数,我们完全可以不考虑函数内部是如何实现的,专注于编写业务代码。优化代码时,目光只需要集中在这些稳定坚固的函数内部即可。</li>
<li></li>
</ul>
</ol>
</div>
<script>
//假设我们需要对一个字符串做一些列操作,如下,为了方便举例,我们只对一个字符串做两种操作,
//我们定义了一个新函数shout,先调用toUpperCase,
//然后把返回值传给exclaim函数,这样做有什么不好呢?
//不优雅,如果做得事情一多,嵌套的函数会非常深,
//而且代码是由内往外执行,不直观,
//我们希望代码从右往左执行,这个时候我们就得使用组合。
// 函数的合成;
// 不优雅的例子
var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '!'; };
var shout = function(x){
return exclaim(toUpperCase(x));
};
shout("send in the clowns");
//=> "SEND IN THE CLOWNS!"
// 优雅的例子;
//定义compose
var compose = (...args) => x => args.reduceRight((value, item) => item(value), x);
var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '!'; };
var exclaim222 = function(x) { return x + '7777777'; };
shout("send in the clowns");
//=> "SEND IN THE CLOWNS!"
//函数
var add = function(x) {
return function(y) {
return x + y;
};
};
//es6写法
var add = x => (y => x + y);
// reduce 实现函数的合并;
var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '!'; };
var compose22 = function(...args){
return function(x){
return args.reduceRight(function(pre, cur){
return cur(pre);
},x);
}
}
// 函数第一次执行compose22(exclaim, toUpperCase),记住 自己的args 传入待传入的数组,
// 再次执行的时候,reduce 开始递归执行,初始值为传入的x;
let aaa=compose22(exclaim, toUpperCase)("aaaa");
console.log(aaa);
</script>
</body>
</html>