函数式编程
一、编程范式
1、面向过程编程:将编程任务当作完成一件事情,这件事情需要按步骤完成。先做什么,再做什么,然后做什么(注重于步骤)。
2、面向对象编程:把功能组织成对象,然后相关的操作作为对象的方法。
3、函数式编程:把功能分解为一系列独立的函数,通过函数间相互调用来完成功能。
二、函数式的优缺点
优点:
1、函数式编程能提高复用性和扩展性
每个函数就像一块积木,能随时拼入新积木,也能随时取出积木去复用。
比如需要写一个算法:把数字乘以 2 然后减 1(后面需要扩展),分别以面向对象和函数式编写。
面向对象
function CalcNumber(number) {
this.number = number
}
CalcNumber.prototype.calc = function () {
return this.number * 2 - 1
}
const a = new CalcNumber(2)
console.log(a.calc()) //3
若其他地方需要在该算法的基础上再除以2,就得写一个子类来继承父类,再重写方法。
//继承构造函数
function CalcNumberSon(number) {
CalcNumber.call(this, number)
}
//继承原型链
CalcNumberSon.prototype = new CalcNumber()
//重写方法
CalcNumberSon.prototype.calc = function () {
return (this.number * 2 - 1) / 2
}
const b = new CalcNumberSon(2)
console.log(b.calc()) //1.5
若另一个地方需要的是在该算法的基础上加2(而不是除以2),就又得创建一个子类继承父类,再重写方法...
函数式
function multiplyTow(num) {
return num * 2
}
function addOne(num) {
return num - 1
}
var num = multiplyTow(2)
num1 = addOne(num)
console.log(num1) //3
而函数式写法只需要再写一个除以2的函数,在需要的地方调用就行。
function exceptTow(num) {
return num / 2
}
num2 = exceptTow(num1)
console.log(num2) //1.5
以后需要哪个函数都可以直接拿来随意组合使用。
2、函数式编程能很好的结合 Tree Shaking 去使用,而面向对象编程方案无法记录
缺点:
函数过多比较难管理,逻辑性没有面向对象强。涉及到业务逻辑的代码,还是使用面向对象编程,更加擅长组织逻辑。
三、如何写好函数式编程
1、保证是纯函数:一个函数的返回结果只依赖于它的参数,同样的输入必定得到同样的输出
非纯函数(由于变量 a 是函数 add() 的外部变量且不受该函数控制,故无法保证add()的输出)
var a = 10;
function add(num) {
return a + num
}
转化为纯函数 -> 只需将a作为参数传入函数中,这时add()输出全都由传入的参数决定。
function add(a, num) {
return a + num
}
2、减少函数副作用:函数的副作用就是函数会影响外部数据,如全局变量
副作用
var b = 123;
function bPlus() {
// 若直接操作外部变量,就会改变外部变量
b += 1;
return b;
}
bPlus()
console.log(b) //124
消除函数副作用的方法
基本数据类型:将外部变量作为参数传入,然后函数内部创建一个局部变量来操作。
var c = 123;
function cPlus(c) {
c += 1;
return c;
}
var c2 = cPlus(c)
console.log(c, c2) //123, 124
引用数据类型:将外部变量作为参数传入,然后函数内部拷贝一份,再去操作拷贝出来的那份
// 对象
var obj = {a: 1};
function objPlus(obj) {
var _obj = Object.create(obj)
_obj.a += 1
return _obj
}
var obj2 = objPlus(obj)
console.log(obj, obj2) //{a: 1}, {a: 2}
// 数组
var arr = [1];
function arrPlus(arr) {
var _arr = [...arr]
_arr[0] += 1
return _arr
}
var arr2 = arrPlus(arr)
console.log(arr, arr2) //[1], [2]
3、工程化下的函数编程
传统的面向对象,直接暴露类。
function class1() {
}
// es6
export default class1; //暴露
import class1 from './xx.js'; //引入
// commonjs
module.exports = class1;
const class1 = require('./xx.js')
函数式
// es6
export function f1() {
}
export function f2() {
}
import {f1} from './xx.js';
import * as all from './xx.js';
// commonjs
function f1() {
}
function f2() {
}
exports.f1 = f1;
exports.f2 = f2;
const f1 = require('./xx.js').f1;
const all = require('./xx.js');
转载自:https://juejin.cn/post/7221923392260669497