命令式
面向过程编程
面向过程(POP)是以过程为中心的编程思想。
它首先分析出问题的解决步骤,再按解决步骤设计对应的函数,最后按顺序调用这些函数从而解决整个问题。
面向过程编程的设计需要注重以下两个问题:
自顶向下:被调用的函数强调层次性,对复杂的问题分层次解决。
结构化编程:设计一个合理的逻辑结构,将解决问题的函数串联起来。
面向对象编程
面向对象(OOP)是以对象为中心的编程思想。
它首先对客观问题或事物抽象成一个类,然后调用类生成实例对象,通过实例对象的方法解决问题。
关于JavaScript面向对象编程,朋友们可以看我的往期文章:深入理解原型链与继承
面向对象的三个特性
封装:可以把属性和方法封装到一个类中,并且类与类之间是相互隔离的。
继承:子类可以继承父类的属性和方法,即派生类可以重用基类的属性和方法。
多态:多个对象可以共享相同的外部接口,通过不同的实例对象执行不同的行为。
面向对象的五个设计原则
单一职责原则(Single Responsibility Principle):软件模块应该有且只有一个改变的原因。
开放封闭原则(Open Close Principle):软件模块应该是可扩展,而不可修改的。
里氏替换原则(Liskov Substitution Principle):派生类(子类)对象可以在程式中代替其基类(超类)对象。
依赖倒置原则(Dependence Inversion Principle):程序要依赖于抽象接口,不要依赖于具体实现。
接口隔离原则(Interface Segregation Principle):一个类对另外一个类的依赖性应当是建立在最小的接口上。
声明式
函数式编程
函数式编程(FP)是以函数为中心的编程思想。
它通过把功能分解为一系列独立的函数,通过函数间相互调用来完成功能。
first class function:函数可以传递给其他变量或作为参数。
pure function:纯函数无副作用,不能影响外部状态。
currying:通过函数柯里化,能够支持惰性计算。
// 柯里化函数的原理:递归 + 闭包
function currying(fn, ...initArgs) {
return function (...newArgs) {
const args = [...initArgs, ...newArgs]
return args.length === fn.length
? fn.apply(this, args)
: currying.call(this, fn, ...args)
}
}
// 测试用例
function test(a, b, c){
return a + b + c
}
const add = currying(test)
console.log(add(1, 3, 5)) // 9
console.log(add(1, 3)(5)) // 9
console.log(add(1)(3, 5)) // 9
console.log(add(1)(3)(5)) // 9
composition:独立的函数经过组合实现特定的功能。
function compose(f, g) {
return function (x) {
return f(g(x))
}
}
const g = (x) => x * 2
const f = (x) => x + 2
compose(f, g)(2)
functor:用于实现副作用可控
类:functor|方法:map()
class Functor {
static of(value) {
return new Functor(value)
}
constructor(value) {
this.value = value
}
map(fn) {
return Functor.of(fn(this.value))
}
}
const container = Functor.of(2).map(x => x + 2)
console.log(container) // Functor { value: 4 }
monad:用于拍平嵌套的容器(函子)
类:monad|方法:join()、flatMap()
class Monad extends Functor {
static of(value) {
return new Monad(value)
}
constructor(value) {
super(value)
}
join() {
return this.value
}
map(fn) {
return Monad.of(fn(this.value))
}
flatMap(fn) {
return this.map(fn).join()
}
}
// 嵌套的容器
const container_1 = Monad.of(2).map(x => Monad.of(x + 2))
console.log(container_1) // Functor { value: Functor { value: 4 } }
// 拍平后的容器(注意:仅能拍平两层嵌套的容器(函子))
const container_2 = Monad.of(2).flatMap(x => Monad.of(x + 2))
console.log(container_2) // Functor { value: 4 }
applicative:用于分别对两个容器进行取值
新增类:applicative|方法:ap()
class Applicative extends Functor {
static of(value) {
return new Applicative(value)
}
constructor(value) {
super(value)
}
map(fn) {
return Applicative.of(fn(this.value))
}
ap(other) {
return other.map(this.value)
}
}
// 注意:需要利用上述柯里化后的函数 add
const container_3 = Applicative.of(add(2))
.ap(Applicative.of(2))
.ap(Applicative.of(2))
console.log(container_3) // Functor { value: 6 }
响应式编程
响应式编程(RP)是一种面向数据流和变化传播的编程范式。