{T}

FP与OOP编程范式入门

一、编程范式概述

1.1 什么是编程范式

概念说明
编程范式(Programming Paradigm)代表着编写代码的方式或风格。不同的编程范式提供了不同的思维模式和代码组织方式。

三种主流范式

缩写英文全称中文含义核心思想
FPFunctional Programming函数式编程以函数为核心,强调纯函数和数据不可变
OOPObject-Oriented Programming面向对象编程以对象为核心,强调抽象、封装、继承、多态
FRPFunctional Reactive Programming函数响应式编程结合函数式和响应式,处理异步数据流

注意事项

  • 编程范式不是互斥的,一个项目中可以混合使用多种范式
  • 选择哪种范式取决于场景、团队能力和个人习惯
  • 现代前端框架(Vue、React)偏向函数式编程风格

二、函数式编程(FP)

2.1 核心概念

概念说明
函数式编程将程序分解为一系列函数,每个函数完成特定的、独立的任务。强调数据的输入输出,避免副作用。

核心特点

code
函数式编程三大特征:
│
├──  确定的输入输出
│   ├── 相同输入必定得到相同输出
│   ├── 函数执行结果可预测
│   └── 便于测试和调试
│
├──  无副作用
│   ├── 不修改外部状态
│   ├── 不创建 DOM 节点
│   └── 不发起 HTTP 请求
│
└──  引用透明
    ├── 函数调用可被返回值替换
    ├── IDE 友好,易于跳转查看
    └── 代码逻辑清晰易懂

2.2 实战案例:用户登录表单

需求描述

实现一个用户登录表单:

  • 输入用户名和密码
  • 校验:用户名和密码必填,密码长度需大于 6 位
  • 校验通过后打印用户信息并提示登录成功
  • 校验失败提示"用户名或密码不符合要求"

面向过程实现(对比)

javascript
//  面向过程:代码耦合度高,难以复用

// 获取 DOM 节点
const form = document.querySelector('#loginForm');
const usernameInput = document.querySelector('#username');
const passwordInput = document.querySelector('#password');

// 绑定事件
form.addEventListener('submit', function(e) {
  e.preventDefault(); // 阻止默认提交
  
  // 读取输入值
  const username = usernameInput.value;
  const password = passwordInput.value;
  
  // 校验逻辑
  if (!username || !password || password.length <= 6) {
    alert('用户名或密码不符合要求');
    return;
  }
  
  // 处理数据
  const user = { username, password };
  console.log('用户信息:', user);
  alert('登录成功');
});

面向过程的问题

  • 所有逻辑写在一起,耦合度高
  • 难以复用和扩展
  • 不易维护和测试

函数式编程实现

javascript
//  函数式编程:逻辑清晰,易于复用和维护

// ========== 函数定义 ==========

/**
 * 创建表单实例
 * @param {string} formId - 表单 ID
 * @param {Function} handler - 提交处理函数
 */
function createForm(formId, handler) {
  const form = document.querySelector(`#${formId}`);
  form.addEventListener('submit', (e) => {
    e.preventDefault();
    handler();
  });
}

/**
 * 获取用户输入
 * @param {string} usernameId - 用户名输入框 ID
 * @param {string} passwordId - 密码输入框 ID
 * @returns {Object} 用户输入数据
 */
function getUserInput(usernameId, passwordId) {
  const username = document.querySelector(`#${usernameId}`).value;
  const password = document.querySelector(`#${passwordId}`).value;
  return { username, password };
}

/**
 * 创建用户对象
 * @param {Object} input - 用户输入数据
 * @param {boolean} needValidate - 是否需要校验
 * @returns {Object|null} 用户对象或 null
 */
function createUser(input, needValidate = true) {
  if (needValidate && !validate(input)) {
    return null;
  }
  
  return {
    username: input.username,
    password: input.password,
    createdAt: new Date().toISOString()
  };
}

/**
 * 校验用户输入
 * @param {Object} input - 用户输入数据
 * @returns {boolean} 校验结果
 */
function validate(input) {
  const { username, password } = input;
  
  // 可扩展的校验规则
  const rules = [
    { check: () => !!username, message: '用户名不能为空' },
    { check: () => !!password, message: '密码不能为空' },
    { check: () => password.length > 6, message: '密码长度必须大于 6 位' }
  ];
  
  return rules.every(rule => rule.check());
}

/**
 * 提示用户
 * @param {string} message - 提示消息
 */
function showMessage(message) {
  alert(message);
}

// ========== 业务逻辑组合 ==========

/**
 * 登录处理函数
 */
function submitHandler() {
  // 1. 获取输入
  const input = getUserInput('username', 'password');
  
  // 2. 创建用户(带校验)
  const user = createUser(input, true);
  
  // 3. 处理结果
  if (user) {
    console.log('用户信息:', user);
    showMessage('登录成功');
  } else {
    showMessage('用户名或密码不符合要求');
  }
}

// ========== 初始化 ==========

createForm('loginForm', submitHandler);

函数式编程优势

优势说明
逻辑清晰每个函数职责单一,易于理解
易于复用createFormvalidate 等函数可在多处使用
便于扩展新增校验规则只需修改 validate 函数
易于维护问题定位精准,修改某个函数不影响其他部分
IDE 友好函数跳转方便,代码提示完善

2.3 函数式编程最佳实践

javascript
// ========== 纯函数示例 ==========

//  纯函数:相同输入必定得到相同输出,无副作用
function add(a, b) {
  return a + b;
}

function formatUserName(firstName, lastName) {
  return `${firstName} ${lastName}`;
}

//  非纯函数:依赖外部状态,有副作用
let count = 0;
function increment() {
  count++; // 修改外部状态
  return count;
}

function logMessage(message) {
  console.log(message); // 产生副作用(I/O 操作)
}


// ========== 不可变性示例 ==========

//  不可变操作:返回新对象,不修改原对象
const user = { name: 'Tom', age: 25 };

function updateUserAge(user, newAge) {
  return { ...user, age: newAge }; // 返回新对象
}

const updatedUser = updateUserAge(user, 26);
console.log(user);       // { name: 'Tom', age: 25 } - 原对象未变
console.log(updatedUser); // { name: 'Tom', age: 26 }

//  可变操作:直接修改原对象
function updateUserAgeMutable(user, newAge) {
  user.age = newAge; // 直接修改原对象
  return user;
}


// ========== 高阶函数示例 ==========

// 高阶函数:接收函数作为参数,或返回函数
function createValidator(rules) {
  return function(input) {
    return rules.every(rule => rule.check(input));
  };
}

const passwordRules = [
  { check: (pwd) => pwd.length >= 8, message: '至少 8 位' },
  { check: (pwd) => /[A-Z]/.test(pwd), message: '包含大写字母' },
  { check: (pwd) => /[0-9]/.test(pwd), message: '包含数字' }
];

const validatePassword = createValidator(passwordRules);

console.log(validatePassword('abc123'));      // false
console.log(validatePassword('Abcdefg123'));  // true

2.4 现代框架中的函数式编程

React Hooks

javascript
import React, { useState, useEffect } from 'react';

//  React 函数组件 + Hooks:函数式编程思想
function UserForm() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  // 纯函数处理事件
  const handleSubmit = () => {
    const user = createUser({ username, password });
    if (user) {
      console.log('登录成功', user);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        value={username} 
        onChange={(e) => setUsername(e.target.value)} 
      />
      <input 
        type="password"
        value={password} 
        onChange={(e) => setPassword(e.target.value)} 
      />
      <button type="submit">登录</button>
    </form>
  );
}

Vue 3 Composition API

javascript
import { ref, computed } from 'vue';

//  Vue 3 组合式 API:函数式编程思想
export default {
  setup() {
    const username = ref('');
    const password = ref('');

    // 纯函数校验
    const isValid = computed(() => {
      return username.value && 
             password.value && 
             password.value.length > 6;
    });

    const handleSubmit = () => {
      if (isValid.value) {
        console.log('登录成功', {
          username: username.value,
          password: password.value
        });
      }
    };

    return { username, password, isValid, handleSubmit };
  }
};

三、面向对象编程(OOP)

3.1 核心概念

概念说明
面向对象编程将程序分解为一系列对象,每个对象包含数据(属性)和行为(方法)。通过抽象、封装、继承、多态来组织代码。

三大特性

code
面向对象编程三大特性:
│
├──  封装性
│   ├── 属性和方法封装在类中
│   ├── 外部不能直接访问内部数据
│   └── 通过公共方法操作内部状态
│
├──  继承性
│   ├── 子类继承父类的属性和方法
│   ├── 避免代码重复
│   └── 建立类之间的层级关系
│
└──  多态性
    ├── 同一个方法名,不同对象有不同实现
    ├── 提高代码灵活性
    └── 降低代码耦合度

3.2 实战案例:用户登录表单(OOP 实现)

javascript
// ========== 类定义 ==========

/**
 * 校验器类
 * 提供静态校验方法
 */
class Validator {
  /**
   * 校验用户名和密码
   * @param {string} username - 用户名
   * @param {string} password - 密码
   * @returns {boolean} 校验结果
   */
  static validate(username, password) {
    if (!username || !password) {
      return false;
    }
    if (password.length <= 6) {
      return false;
    }
    return true;
  }
}

/**
 * 用户类
 * 封装用户数据和行为
 */
class User {
  // 私有属性(ES2022 新特性)
  #username;
  #password;

  constructor(username, password) {
    this.#username = username;
    this.#password = password;
  }

  // Getter 方法
  get username() {
    return this.#username;
  }

  get password() {
    return this.#password;
  }

  /**
   * 用户问候语
   */
  greet() {
    console.log(`欢迎用户:${this.#username}`);
  }

  /**
   * 打印用户信息
   */
  printInfo() {
    console.log({
      username: this.#username,
      password: '******', // 脱敏显示
      createdAt: new Date().toISOString()
    });
  }
}

/**
 * 用户表单类
 * 封装表单逻辑
 */
class UserForm {
  // 私有属性
  #form;
  #usernameInput;
  #passwordInput;

  constructor(formId) {
    // 初始化 DOM 引用
    this.#form = document.querySelector(`#${formId}`);
    this.#usernameInput = document.querySelector('#username');
    this.#passwordInput = document.querySelector('#password');

    // 绑定事件
    this.#init();
  }

  // 私有方法:初始化
  #init {
    this.#form.addEventListener('submit', (e) => {
      e.preventDefault();
      this.#handleSubmit();
    });
  }

  // 私有方法:提交处理
  #handleSubmit {
    const username = this.#usernameInput.value;
    const password = this.#passwordInput.value;

    // 使用 Validator 类进行校验
    if (!Validator.validate(username, password)) {
      alert('用户名或密码不符合要求');
      return;
    }

    // 创建 User 对象
    const user = new User(username, password);
    
    // 调用 User 对象的方法
    user.printInfo();
    user.greet();
    
    alert('登录成功');
  }
}

// ========== 初始化 ==========

const loginForm = new UserForm('loginForm');

OOP 优势

特性说明示例
抽象从具体问题中抽象出通用概念UserValidatorUserForm
封装数据和方法封装在类中私有属性 #username#password
复用类可以在多个地方实例化创建多个表单:new UserForm('registerForm')
扩展通过继承扩展功能可创建 AdminUser extends User
多态同一方法不同实现不同用户类型的 greet() 方法

3.3 继承与多态示例

javascript
// ========== 基类:用户 ==========

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  // 基础问候方法
  greet() {
    return `你好,我是 ${this.name}`;
  }

  // 获取权限
  getPermissions() {
    return ['read'];
  }
}

// ========== 子类:管理员 ==========

class AdminUser extends User {
  constructor(name, email, department) {
    super(name, email); // 调用父类构造函数
    this.department = department;
  }

  // 重写(Override)父类方法 - 多态
  greet() {
    return `你好,我是管理员 ${this.name},负责 ${this.department}`;
  }

  // 扩展父类权限
  getPermissions() {
    return [...super.getPermissions(), 'write', 'delete'];
  }

  // 新增方法
  banUser(user) {
    console.log(`${this.name} 封禁了用户 ${user.name}`);
  }
}

// ========== 子类:VIP用户 ==========

class VIPUser extends User {
  constructor(name, email, level) {
    super(name, email);
    this.level = level;
  }

  // 多态:不同的问候实现
  greet() {
    return `你好,我是 VIP${this.level} 用户 ${this.name}`;
  }

  // VIP 特有方法
  getDiscount() {
    return this.level === 1 ? 0.9 : 0.8;
  }
}

// ========== 使用示例 ==========

const normalUser = new User('小明', 'xiaoming@example.com');
const admin = new AdminUser('张三', 'zhangsan@example.com', '技术部');
const vip = new VIPUser('李四', 'lisi@example.com', 2);

// 多态:同一个方法,不同的行为
console.log(normalUser.greet());  // 你好,我是 小明
console.log(admin.greet());       // 你好,我是管理员 张三,负责 技术部
console.log(vip.greet());         // 你好,我是 VIP2 用户 李四

// 继承:复用父类功能
console.log(normalUser.getPermissions()); // ['read']
console.log(admin.getPermissions());       // ['read', 'write', 'delete']

// 扩展:子类特有功能
admin.banUser(normalUser); // 张三 封禁了用户 小明
console.log(vip.getDiscount()); // 0.8

3.4 OOP 在前端框架中的应用

NestJS(后端框架)

typescript
//  NestJS 典型的 OOP 风格

@Controller('users')
export class UserController {
  // 依赖注入
  constructor(private readonly userService: UserService) {}

  @Get()
  getUsers() {
    return this.userService.findAll();
  }

  @Post()
  createUser(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }
}

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}

  findAll(): Promise<User[]> {
    return this.userRepository.find();
  }

  create(createUserDto: CreateUserDto): Promise<User> {
    const user = this.userRepository.create(createUserDto);
    return this.userRepository.save(user);
  }
}

Angular(前端框架)

typescript
//  Angular 完全面向对象

@Component({
  selector: 'app-user',
  template: `
    <div *ngFor="let user of users">
      {{ user.name }}
    </div>
  `
})
export class UserComponent implements OnInit {
  users: User[] = [];

  // 依赖注入
  constructor(private userService: UserService) {}

  ngOnInit() {
    this.loadUsers();
  }

  loadUsers() {
    this.userService.getUsers().subscribe(users => {
      this.users = users;
    });
  }
}

四、函数响应式编程(FRP)

4.1 核心概念

概念说明
函数响应式编程结合了函数式编程和响应式编程的思想,主要用于处理异步数据流和事件流。

核心特点

code
函数响应式编程特征:
│
├──  数据流驱动
│   ├── 一切皆数据流
│   ├── 数据变化自动传播
│   └── 声明式编程风格
│
├──  异步场景优化
│   ├── 处理复杂的事件组合
│   ├── 用户输入防抖/节流
│   └── API 请求流式处理
│
└──  组合能力强
    ├── 多个数据流合并
    ├── 数据转换链式调用
    └── 错误处理统一管理

4.2 应用场景

场景一:表单实时校验

javascript
// 使用 RxJS 实现输入框实时校验

import { fromEvent } from 'rxjs';
import { map, debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';

const usernameInput = document.querySelector('#username');
const submitBtn = document.querySelector('#submitBtn');

// 创建输入事件流
fromEvent(usernameInput, 'input')
  .pipe(
    map(event => event.target.value),           // 提取输入值
    debounceTime(300),                          // 防抖:300ms
    distinctUntilChanged(),                     // 去重:值相同时不触发
    filter(value => value.length >= 3),         // 过滤:长度 >= 3
    map(value => validateUsername(value))       // 校验
  )
  .subscribe(result => {
    submitBtn.disabled = !result.isValid;
    console.log(result.message);
  });

function validateUsername(username) {
  if (username.length < 3) {
    return { isValid: false, message: '用户名至少 3 个字符' };
  }
  if (!/^[a-zA-Z0-9_]+$/.test(username)) {
    return { isValid: false, message: '只能包含字母、数字、下划线' };
  }
  return { isValid: true, message: '用户名可用' };
}

场景二:好友推荐列表(课堂案例)

需求描述

  • 显示好友推荐列表(3 条)
  • 点击删除按钮移除一条推荐
  • 删除后自动请求新数据填充
  • 类似 QQ/微信的好友推荐功能
javascript
import { fromEvent, from } from 'rxjs';
import { mergeMap, scan, startWith } from 'rxjs/operators';

// 模拟 API 请求
function fetchRecommendation() {
  return from(
    fetch('/api/recommendation')
      .then(res => res.json())
      .then(data => data.user)
  );
}

// 删除事件流
const deleteClick$ = fromEvent(document, 'click')
  .pipe(
    filter(event => event.target.classList.contains('delete-btn')),
    mergeMap(() => fetchRecommendation())  // 删除后立即请求新数据
  );

// 订阅删除事件
deleteClick$.subscribe(newUser => {
  console.log('新推荐用户:', newUser);
  // 更新 UI
  updateRecommendationList(newUser);
});

4.3 RxJS 核心概念

javascript
import { Observable, from, of, interval, fromEvent } from 'rxjs';
import { map, filter, mergeMap, take, switchMap } from 'rxjs/operators';

// ========== Observable(可观察对象)==========

// 创建 Observable
const observable$ = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  subscriber.complete();
});

// 订阅 Observable
observable$.subscribe({
  next: value => console.log(value),
  complete: () => console.log('完成')
});
// 输出:1, 2, 3, 完成


// ========== 常用创建操作符 ==========

// from:从数组/Promise 创建
const fromArray$ = from([1, 2, 3, 4, 5]);

// of:创建单个值
const singleValue$ = of('Hello');

// interval:定时发送递增值
interval(1000) // 每秒发送 0, 1, 2, 3...
  .pipe(take(5)) // 只取前 5 个
  .subscribe(value => console.log(value));


// ========== 常用管道操作符 ==========

from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
  .pipe(
    filter(num => num % 2 === 0),  // 过滤偶数
    map(num => num * 10),          // 乘以 10
    take(3)                        // 只取前 3 个
  )
  .subscribe(value => console.log(value));
// 输出:20, 40, 60


// ========== 实战:搜索建议 ==========

const searchInput = document.querySelector('#search');

fromEvent(searchInput, 'input')
  .pipe(
    map(event => event.target.value),
    debounceTime(500),              // 防抖 500ms
    distinctUntilChanged(),         // 去重
    filter(query => query.length > 0),
    switchMap(query =>               // 切换到最新的搜索请求
      from(fetch(`/api/search?q=${query}`).then(res => res.json()))
    )
  )
  .subscribe(results => {
    console.log('搜索结果:', results);
    // 渲染搜索建议列表
    renderSuggestions(results);
  });

4.4 Vue 3 中的响应式

javascript
import { ref, computed, watch, watchEffect } from 'vue';

//  Vue 3 响应式系统:简化版的 FRP

export default {
  setup() {
    // 响应式数据(数据流)
    const count = ref(0);
    const doubleCount = computed(() => count.value * 2);

    // 自动追踪依赖的副作用(响应式)
    watchEffect(() => {
      console.log(`count 变化了:${count.value}`);
    });

    // 监听特定数据源
    watch(count, (newVal, oldVal) => {
      console.log(`count 从 ${oldVal} 变为 ${newVal}`);
    });

    return { count, doubleCount };
  }
};

五、三种编程范式对比

5.1 核心对比

维度函数式编程(FP)面向对象编程(OOP)函数响应式编程(FRP)
核心思想函数 + 数据流对象 + 封装数据流 + 响应式
代码组织函数组合类和对象Observable + 操作符
状态管理不可变数据可变状态(封装)流式传播
适用场景数据转换、逻辑复用业务建模、大型应用异步事件、实时数据
学习曲线中等较陡较陡
框架代表React、Vue 3Angular、NestJSRxJS、RxJava
优势逻辑清晰、易测试易于建模、结构化异步处理能力强
劣势业务建模不直观继承滥用、耦合学习成本高

5.2 如何选择

code
编程范式选择指南:
│
├──  选择函数式编程(FP)当:
│   ├── 需要大量数据转换和处理
│   ├── 希望代码易于测试和维护
│   ├── 使用 React/Vue 等现代框架
│   └── 团队偏好声明式编程风格
│
├──  选择面向对象编程(OOP)当:
│   ├── 业务逻辑复杂,需要建模
│   ├── 大型企业级应用
│   ├── 使用 Angular/NestJS 等框架
│   └── 团队有 Java/C# 背景
│
└──  选择函数响应式编程(FRP)当:
    ├── 处理复杂的异步事件流
    ├── 实时数据更新场景
    ├── 需要灵活的事件组合
    └── 使用 RxJS/RxJava 等库

5.3 实际项目中的混合使用

javascript
// ========== 混合使用示例 ==========

//  OOP:定义类和对象
class UserService {
  private users: User[] = [];

  //  FP:纯函数处理数据
  private validateUser(user: User): boolean {
    return !!user.name && user.age >= 0;
  }

  //  FP:不可变操作
  addUser(user: User): User[] {
    if (!this.validateUser(user)) {
      throw new Error('Invalid user');
    }
    this.users = [...this.users, user]; // 不可变更新
    return this.users;
  }

  //  FP:函数组合
  getAdultUsers(): User[] {
    return this.users
      .filter(user => user.age >= 18)
      .map(user => ({ ...user, isAdult: true }));
  }
}

//  FRP:处理异步事件
fromEvent(searchInput, 'input')
  .pipe(
    debounceTime(300),
    map(event => event.target.value),
    switchMap(query => userService.search(query))
  )
  .subscribe(results => {
    console.log('搜索结果:', results);
  });

六、常见问题与解决方案

问题原因解决方案
FP 代码难以理解过度使用高阶函数和组合保持函数简单,添加清晰的命名和注释
OOP 类继承层次过深过度使用继承优先使用组合而非继承(Composition over Inheritance)
FP 无状态导致频繁传参避免副作用过度适当使用闭包或模块级状态
OOP 类之间耦合严重职责划分不清遵循单一职责原则,使用依赖注入
FRP 代码调试困难数据流复杂使用 RxJS 的 tap 操作符打印中间状态
不知道选哪种范式对场景理解不足从简单开始,逐步混合使用,根据场景调整
FP 性能问题频繁创建新对象对于大数据量,考虑使用不可变数据库(如 Immer)
OOP 灵活性不足类设计过于僵化使用接口和抽象类,增加扩展点

七、学习要点总结

核心要点

  1. 编程范式是工具:没有最好的范式,只有最适合场景的范式
  2. 函数式编程核心:纯函数、不可变性、函数组合、无副作用
  3. 面向对象编程核心:抽象、封装、继承、多态
  4. 函数响应式编程核心:数据流、异步处理、声明式
  5. 混合使用:现代项目中通常会混合使用多种范式

行动建议

code
学习路径:
│
├──  第一阶段:理解概念(1 周)
│   ├── 理解三种范式的核心思想
│   ├── 完成课堂中的登录表单示例
│   └── 对比不同实现的优劣
│
├──  第二阶段:实战练习(2 周)
│   ├── 用 FP 重构现有代码中的工具函数
│   ├── 用 OOP 设计一个简单的业务模块
│   └── 用 RxJS 实现搜索建议功能
│
└──  第三阶段:框架应用(持续)
    ├── React/Vue 中应用 FP 思想
    ├── NestJS 中应用 OOP 思想
    └── 根据场景灵活选择范式

八、延伸学习资源

官方资源

推荐书籍

  • 《JavaScript 函数式编程》
  • 《JavaScript 设计模式》
  • 《JavaScript 高级程序设计》第 8 章:对象、类与面向对象编程

练习建议

  1. 练习 1:将现有项目中的工具函数改造成纯函数
  2. 练习 2:设计一个购物车类,应用封装、继承、多态
  3. 练习 3:使用 RxJS 实现一个自动完成的搜索框
  4. 练习 4:对比同一个需求用 FP 和 OOP 实现的差异
  5. 练习 5:在 React 项目中应用函数式编程思想(自定义 Hooks)

延伸思考

code
思考题:
│
├──  为什么 Vue 3 和 React 都偏向函数式编程?
├──  为什么 NestJS 和 Angular 选择面向对象?
├──  在什么场景下应该使用 FRP?
└──  如何在团队中推广最佳实践?

附录:编程范式速查表

概念FPOOPFRP
基本单元函数类/对象Observable
数据不可变可变(封装)流式
状态无状态对象状态自动传播
控制流函数组合方法调用操作符链
复用方式函数复用继承/组合操作符复用
核心原则纯函数、无副作用封装、继承、多态响应式、声明式