编程范式
编程范式就是编程风格,主流的有命令式、函数式、面向对象等。JavaScript 是一种多范式编程语言,支持多种编程范式,允许开发者根据需求选择适合的编程风格。
一、命令式
通过一系列命令(或语句)来改变程序的状态。
命令式编程的核心思想是:告诉计算机做什么以及如何做。 命令式也是新手学习编程的最简单方式。
1.1 特点
- 状态管理:命令式编程通过变量的状态变化来表示程序的当前状态。
- 顺序执行:代码按照编写的顺序逐行执行。
- 可变性:变量的值可以在程序执行的过程中被多次修改。
- 副作用:命令式编程中,函数的执行会产生副作用,即函数执行后会影响到程序的其他部分。
let sum = 0
for (let i = 1; i <= 10; i++) {
sum += i
}
console.log(sum) // 输出 55
2
3
4
5
在这个例子中,sum 的值在每次循环时都发生变化,这是典型的命令式编程风格。
二、函数式
程序主要由函数的组合而成。它强调函数的应用和函数之间的组合,尽量避免状态变化和副作用。
特点
函数是"第一等公民"
所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。只用"表达式",不用"语句"
- "表达式"(expression)是一个单纯的运算过程,总是有返回值;
- "语句"(statement)是执行某种操作,没有返回值。
函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
没有"副作用"
所谓"副作用(side effect)",指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。 函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。不修改状态
上一点已经提到,函数式编程只是返回新的值,不修改系统变量。因此,不修改变量,也是它的一个重要特点。 在其他类型的语言中,变量往往用来保存"状态"(state)。不修改变量,意味着状态不能保存在变量中。函数式编程使用参数保存状态,最好的例子就是递归。引用透明(Referential transparency) 指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。
特征
- 纯函数:函数式编程中的函数通常是“纯函数”,即相同的输入总是产生相同的输出,且没有副作用。
- 不可变性:状态和数据通常是不可变的,即一旦创建就不能改变。
- 高阶函数:函数可以作为参数传递给其他函数,或者作为返回值从函数中返回。
- 函数组合:通过组合简单的函数来构建复杂的行为。
const numbers = [1, 2, 3, 4, 5]
const doubledNumbers = numbers.map((n) => n * 2)
console.log(doubledNumbers) // 输出 [2, 4, 6, 8, 10]
2
3
在这个例子中,map 函数是一个高阶函数,它接受一个函数作为参数,并返回一个新数组,这是函数式编程的典型用法。
三、面向对象
面向对象编程通过“对象”来组织代码。对象是具有状态(属性)和行为(方法)的实体。面向对象编程的核心概念包括类、对象、继承和多态等。
- 封装:将数据和操作数据的方法封装在对象内部,隐藏对象的内部实现。
- 继承:通过继承机制,子类可以继承父类的属性和方法,促进代码的重用。
- 多态:不同的对象可以以统一的接口来实现不同的行为。
- 对象:对象是类的实例,它包含了类定义的属性和方法。
class Animal {
constructor(name) {
this.name = name
}
speak() {
console.log(`${this.name} makes a noise.`)
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`)
}
}
const dog = new Dog('Rex')
dog.speak() // 输出 'Rex barks.'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在这个例子中,我们定义了一个 Animal 类和一个继承自它的 Dog 类。Dog 类重写了 speak 方法,这是面向对象编程中多态的体现。
四、总结
- 命令式编程 强调如何去做,通过明确的步骤来管理状态和执行任务。
- 函数式编程 强调声明性的代码,通过函数的组合来实现复杂的逻辑,避免可变状态和副作用。
- 面向对象编程 通过对象和类来组织代码,强调数据和行为的封装与继承。-
简单来说,函数式更加接近计算机科学的本质,更加抽象。命令式更加接近人类的思维方式,更加直观。而面向对象更加接近现实世界的实体,更加具体。