面向对象编程
把现实世界中的事物抽象成程序世界中的类和对象,通过封装,继承和多态来演示事物事件的联系
函数式编程
利用函数把运算过程封装起来,通过组合各种函数来计算结果。函数式编程意味着你可以在更短的时间内编写具有更少错误的代码。假设有个字符串要求小写转大写
const str = 'abcdefg'
const result = str.split('').map(item => item.toUpperCase()).join()
上述的例子就是先用 split 把字符串转换数组,再通过 map 把各元素转换为大写,然后通过 join 把数组转换为字符串。整个过程就是 join(map(split(str))),体现了函数式编程的核心思想:通过函数对数据进行转换。
由此我们可以得到,函数式编程有两个基本特点:
- 通过函数来对数据进行转换
- 通过串联多个函数来求结果
纯函数
无副作用
相同的输入永远会得到相同的输出,且没有任何可观察的副作用
好处:
.可缓存 因为纯函数对相同的输入始终有相同的结果,所以可以把纯函数的结果缓存起来
//模拟记忆函数
//ES5写法
let memorize = function(f) {
let cache = {}
return function () {
let key = JSON.stringify(arguments)
cache[key] = cache[key] || f.apply(f,arguments)
return cache[key]
}
}
//ES6写法
let memorize = function(f) {
let cache = {}
return function (...args) {
let key = args.toString()
cache[key] = cache[key] || f.call(f,...args)
return cache[key]
}
}
透明引用
指一个函数只会用到传递给它的变量以及自己内部创建的变量,不会使用到外部变量
遵循上述两条原则即为纯函数
头等函数
头等函数的意思是指在程序设计语言中,函数被当作头等公民。函数的名字没有特殊含义,它们被当作具有函数类型的普通的变量对待。即可以做到以下三件事:
1.函数可以存储在变量中
2.函数作为参数
3.函数作为返回值
像是闭包、高阶函数、柯里化以及函数组合都是围绕这一特性的应用
高阶函数
1.可以把函数作为参数传递给另一个函数
2.可以把函数作为另一个函数的返回结果
柯里化
把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
//柯里化演示
function checkAge (age) {
let min = 18
return age >= min
}
//普通的纯函数
function checkAge (min,age) {
return age >= min
}
//函数的柯里化
//ES5写法
function checkAge (min) {
return function (age) {
return age >= min
}
}
//ES6写法
let checkAge = min => (age => age >= min)
//柯里化模拟
function curry (func) {
return function curriedFn(...args) {
//判断实参和形参的个数
if(args.length < func.length) {
return function () {
return curriedFn(...args.concat(Array.from(arguments)))
}
}
return func(...args)
}
}
1.柯里化可以让我们给一个函数传递较少的参数,得到一个已经记住了某些固定参数的新函数
2.这是一种对函数参数的’缓存’
3.让函数变得更灵活,让函数的粒度更小
4.可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能
函数组合
如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并成一个函数
1.函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果
2.函数组合默认是从右到左执行
//模拟lodash中的flowRight
//ES5写法
function compose (...args) {
return function (value) {
return args.reverse().reduce(function (acc, fn){
return fn(acc)
}, value
}
}
//es6写法
const compose = (...args) => value => args.reverse().reduce((acc,fn) => fn(acc), value)