内容简介:个人觉得这个定义肥肠生动形象了。函数式编程处处体现着数学的逻辑思想,通过减少外部依赖来避免外部变量的改变对于程式内部状态的改变,使得程序变得简易、声明式、易于维护。这里推荐一下F大的《JS函数式编程指南》,系统介绍了函数式编程的思想。
JS函数式编程思想
- 维基百科定义:函数式编程(英语:functional programming),又称泛函编程,是一种编程范式,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。
个人觉得这个定义肥肠生动形象了。
函数式编程处处体现着数学的逻辑思想,通过减少外部依赖来避免外部变量的改变对于程式内部状态的改变,使得程序变得简易、声明式、易于维护。
这里推荐一下F大的《JS函数式编程指南》,系统介绍了函数式编程的思想。
中文版电子书下载地址走你: https://legacy.gitbook.com/bo...
本文章是自己阅读后的一些理解和记录~
First Class Funtcion
这个概念同样出于书中。规定了变量可以取的值得范围,以及该类型的值可以进行的操作。根据类型的值的可赋值状况,可以把类型分为三类。
- 一级的(first class)。该等级类型的值可以传给子程序作为参数,可以从子程序里返回,可以赋给变量。大多数程序设计语言里,整型、字符类型等简单类型都是一级的。
- 二级的(second class)。该等级类型的值可以传给子程序作为参数,但是不能从子程序里返回,也不能赋给变量。
- 三级的(third class)。该等级类型的值连作为参数传递也不行。
first class function
PS:scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。
因此,function作为变量的一种,可以被储存,当作参数传递,或者被复制给变量等等...
Pure Function
首先弄清纯函数的概念: Pure function
意指相同的輸入,永遠會得到相同的輸出,而且沒有任何顯著的副作用。
它符合两个条件:
- 此函数在相同的输入值时,总是产生相同的输出。函数的输出和当前运行环境的上下文状态无关。
- 此函数运行过程不影响运行环境,也就是无副作用(如触发事件、发起http请求、打印/log等)。
简单来说,也就是当一个函数的输出不受外部环境影响,同时也不影响外部环境时,该函数就是纯函数,也就是它只关注逻辑运算和数学运算,同一个输入总得到同一个输出。
比如 slice
和 splice
,但是 slice
是纯函数,而 splice
不是,因为后者会改变源数据。
这就是强调使用纯函数的原因,因为纯函数相对于非纯函数来说,在可缓存性、可移植性、可测试性以及并行计算方面都有着巨大的优势。
看一下书中的例子:
// impure var minimum = 21; var checkAge = function(age) { return age >= minimum; }; // pure var checkAge = function(age) { var minimum = 21; return age >= minimum; };
在impure 的版本中,checkAge 的結果將取決於 minimum 這個变量,换句话说,除了输入以外,它将取决于系统状态,一旦引用了外部环境,它就不符合pure了。
当然,也可以直接冻结变量,使得状态不再变化,那么它也是一个纯函数:
var immutableState = Object.freeze({ minimum: 21, });
Curry(柯里化)
书中定义柯里化的概念是:你可以只透過部分的參數呼叫一個 function,它會回傳一個 function 去處理剩下的參數。
函数柯里化是一种“预加载”函数的能力,通过传递一到两个参数调用函数,就能得到一个记住了这些参数的新函数。从某种意义上来讲,这是一种对参数的缓存,是一种非常高效的编写函数的方法,将一个低阶函数转换为高阶函数的过程就叫柯里化。
//举个栗子 var checkage = min => (age => age > min); var checkage18 = checkage(18); checkage18(20); // =>true var curry = require('lodash').curry; //柯里化两个纯函数 var match = curry((what, str) => str.match(what)); var filter = curry((f, ary) => ary.filter(f)); //判断字符串里有没有空格 var hasSpaces = match(/\s+/g); hasSpaces("hello world"); // [ ' ' ] hasSpaces("spaceless"); // null var findSpaces = filter(hasSpaces); findSpaces(["tori_spelling", "tori amos"]); // ["tori amos"]
Compose—Functional饲养
假设要对某个字符串做一系列操作,我们做的事情一多,嵌套的层数会非常深。类似于巢状堆积(比如c(b(a())))这种堆砌方式非常不直观,当我们希望代码以平行方式(书中成为左倾)组合执行时,就成为 Compose
compose 的概念直接來自於數學課本,所以compose都有的一个特性:
// 結合律(associativity) var associative = compose(f, compose(g, h)) == compose(compose(f, g), h); // true
PointFree
pointfree 模式指的是,永远不必说出你的数据。它的意思是说,函数无须提及将要操作的数据是什么样的
// 非 pointfree,因為我們提到資料:word var snakeCase = function(word) { return word.toLowerCase().replace(/\s+/ig, '_'); }; // pointfree var snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);
这种风格能够帮助我们减少不必要的命名,让代码保持简洁和通用。
当然,为了在一些函数中写出Point Free的风格,在代码的其它地方必然是不那么Point Free的,这个地方需要自己取舍。
声明式与宣告式代码
// 命令式 var makes = []; for (var i = 0; i < cars.length; i++) { makes.push(cars[i].make); } // 宣告式 var makes = cars.map(function(car) { return car.make; });
命令式代码:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。
声明式代码:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。
命令式的循环要求你必须先实例化一个数组,而且执行完这个实例化语句之后,解释器才继续执行后面的代码。然后再直接迭代 cars 列表,手动增加计数器,就像你开了一辆零部件全部暴露在外的汽车一样。这不是优雅的 程序员 应该做的。
声明式的写法是一个表达式,如何进行计数器迭代,返回的数组如何收集,这些细节都隐藏了起来。它指明的是做什么,而不是怎么做。除了更加清晰和简洁之外,map 函数还可以进一步独立优化,甚至用解释器内置的速度极快的 map 函数,这么一来我们主要的业务代码就无须改动了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Responsive Web Design
Ethan Marcotte / Happy Cog / 2011-6 / USD 18.00
From mobile browsers to netbooks and tablets, users are visiting your sites from an increasing array of devices and browsers. Are your designs ready? Learn how to think beyond the desktop and craft be......一起来看看 《Responsive Web Design》 这本书的介绍吧!