js design(手把手讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在现代 Web 开发中,JavaScript 不仅是实现交互逻辑的核心工具,更是构建复杂系统的重要语言。随着项目规模的扩大,代码的可维护性、扩展性和复用性逐渐成为开发者关注的焦点。如何通过合理的 js design(JavaScript 设计)提升代码质量,是每个开发者需要掌握的关键技能。本文将从基础概念到实战案例,逐步解析 JavaScript 设计的核心原则、经典模式及现代实践,帮助读者在实际开发中构建更优雅的代码结构。


一、基础概念:什么是 JavaScript 设计?

JavaScript 设计是指通过合理的编程范式、代码组织方式及设计模式,提升代码的可读性、可维护性,并减少潜在的 Bug。它不仅涉及语法层面的优化,更包含对架构和抽象思维的思考。例如,通过模块化将功能拆分为独立单元,或利用闭包实现数据隐藏,都是 js design 的具体体现。

设计模式 vs 设计原则

  • 设计模式(Design Patterns):经过验证的、可复用的解决方案,如单例模式、观察者模式。它们是针对特定问题的“模板”,帮助开发者快速解决常见场景。
  • 设计原则(Design Principles):指导代码设计的底层规则,如“开闭原则”(对扩展开放,对修改关闭)。这些原则是设计模式的理论基础。

比喻:设计原则如同建筑设计的力学原理,设计模式则是具体的施工方案,二者共同确保建筑既安全又实用。


二、核心设计原则:构建高质量代码的基石

以下是 JavaScript 开发中至关重要的设计原则,它们为代码设计提供了清晰的指导方向。

1. 单一职责原则(Single Responsibility Principle)

定义:一个函数、类或模块应只负责一项职责。
案例

// ❌ 违反单一职责  
function handleUser(user) {  
  validateUser(user); // 验证逻辑  
  saveToDatabase(user); // 数据库操作  
  sendEmail(user); // 发送邮件  
}  

// ✅ 符合单一职责  
function validateUser(user) { ... }  
function saveToDatabase(user) { ... }  
function sendEmail(user) { ... }  

比喻:就像厨房里的刀具,每把刀只负责一种切割任务(如切菜刀、水果刀),而非一把刀包揽所有功能。

2. 开闭原则(Open/Closed Principle)

定义:软件实体(类、模块等)应对扩展开放对修改关闭
实现方式:通过继承、组合或接口扩展功能,而非直接修改原有代码。
案例

// 原始代码  
class Payment {  
  pay(amount) {  
    console.log(`支付 ${amount} 元`);  
  }  
}  

// ❌ 直接修改(违反开闭原则)  
class PaymentWithDiscount extends Payment {  
  pay(amount) {  
    const discounted = amount * 0.9;  
    super.pay(discounted); // 修改原有逻辑  
  }  
}  

// ✅ 扩展新功能(符合开闭原则)  
class DiscountDecorator {  
  constructor(payMethod) {  
    this.payMethod = payMethod;  
  }  
  pay(amount) {  
    const discounted = amount * 0.9;  
    this.payMethod.pay(discounted);  
  }  
}  

3. 迪米特法则(Law of Demeter)

定义:一个对象应尽量减少与其他对象的直接交互。
目的:降低耦合度,使模块更独立。
案例

// ❌ 违反迪米特法则  
class Order {  
  constructor(user) {  
    this.user = user;  
  }  
  // 直接访问 user 的内部属性  
  getUserEmail() {  
    return this.user.profile.email; // 假设 profile 是 user 的子属性  
  }  
}  

// ✅ 符合迪米特法则  
class User {  
  getProfile() {  
    return { email: this.email }; // 通过接口暴露数据  
  }  
}  

三、经典设计模式详解:从理论到实践

以下模式是 JavaScript 开发中高频使用的设计模式,每个模式均包含代码示例和适用场景。

1. 工厂模式(Factory Pattern)

用途:统一对象的创建逻辑,避免重复代码。
案例

// 创建不同类型的按钮  
const ButtonFactory = {  
  create(type) {  
    const button = document.createElement("button");  
    switch (type) {  
      case "primary":  
        button.style.backgroundColor = "blue";  
        break;  
      case "secondary":  
        button.style.backgroundColor = "gray";  
        break;  
      default:  
        throw new Error("无效类型");  
    }  
    return button;  
  },  
};  

// 使用  
const primaryBtn = ButtonFactory.create("primary");  

2. 单例模式(Singleton Pattern)

用途:确保一个类只有一个实例,常用于全局状态管理。
实现

const singleton = (function() {  
  let instance;  
  function createInstance() {  
    const obj = new Object("I am the singleton");  
    return obj;  
  }  
  return {  
    getInstance: function() {  
      instance = instance || createInstance();  
      return instance;  
    },  
  };  
})();  

// 调用  
const a = singleton.getInstance();  
const b = singleton.getInstance();  
console.log(a === b); // true  

3. 观察者模式(Observer Pattern)

用途:实现对象间“一对多”依赖,当对象状态变化时自动通知依赖者。
案例

class EventManager {  
  constructor() {  
    this.listeners = {};  
  }  
  subscribe(event, callback) {  
    this.listeners[event] = this.listeners[event] || [];  
    this.listeners[event].push(callback);  
  }  
  publish(event, data) {  
    if (this.listeners[event]) {  
      this.listeners[event].forEach(cb => cb(data));  
    }  
  }  
}  

const emitter = new EventManager();  
emitter.subscribe("userLogin", (user) => {  
  console.log(`用户 ${user.name} 登录成功`);  
});  

// 触发事件  
emitter.publish("userLogin", { name: "Alice" }); // 输出日志  

四、现代 JavaScript 设计实践:ES6+ 特性与模式

ES6 及后续版本的语法革新(如类、模块、箭头函数)为 JavaScript 设计带来了新的可能性。

1. 模块化设计(ES6 Modules)

优势

  • 明确的依赖关系(通过 import/export 声明)
  • 避免全局变量污染
    案例
// mathUtils.js  
export const add = (a, b) => a + b;  
export const multiply = (a, b) => a * b;  

// main.js  
import { add } from "./mathUtils.js";  
console.log(add(2, 3)); // 5  

2. 类与继承(ES6 Class)

实现单例模式

class Logger {  
  constructor() {  
    if (!Logger.instance) {  
      Logger.instance = this;  
      this.logs = [];  
    }  
    return Logger.instance;  
  }  
  log(message) {  
    this.logs.push(message);  
  }  
}  

const logger1 = new Logger();  
logger1.log("Hello");  
const logger2 = new Logger(); // 返回已存在的实例  
console.log(logger1 === logger2); // true  

3. 高阶函数与柯里化

用途:增强函数的复用性。
案例

// 柯里化实现可复用的验证函数  
function createValidator(requiredFields) {  
  return (data) => {  
    return requiredFields.every(field => data.hasOwnProperty(field));  
  };  
}  

const validateUser = createValidator(["name", "email"]);  
console.log(validateUser({ name: "Alice" })); // false  
console.log(validateUser({ name: "Alice", email: "a@example.com" })); // true  

五、常见陷阱与解决方案

1. 作用域与闭包滥用

问题:闭包可能导致内存泄漏或意外数据共享。
案例

function createCounter() {  
  let count = 0;  
  return () => count++; // 正确使用闭包保存 count  
}  

// ❌ 错误示例:count 是全局变量  
function badCounter() {  
  return () => count++; // 未声明 count,导致全局污染  
}  

2. 类型检查缺失

解决方案:使用 TypeScript 或运行时类型断言。

// 运行时类型检查  
function addNumbers(a, b) {  
  if (typeof a !== "number" || typeof b !== "number") {  
    throw new TypeError("参数必须为数字");  
  }  
  return a + b;  
}  

六、实战案例:构建一个任务管理器

结合上述知识点,我们实现一个简单的任务管理器,包含以下功能:

  1. 添加任务
  2. 标记任务为已完成
  3. 观察任务状态变化

代码实现

class TaskManager {  
  constructor() {  
    this.tasks = [];  
    this.observers = [];  
  }  

  // 工厂方法创建任务  
  static createTask(description) {  
    return {  
      id: Date.now(),  
      description,  
      completed: false,  
    };  
  }  

  // 添加任务  
  addTask(task) {  
    this.tasks.push(task);  
    this.notify("taskAdded", task);  
  }  

  // 标记完成  
  completeTask(taskId) {  
    const task = this.tasks.find(t => t.id === taskId);  
    if (task) {  
      task.completed = true;  
      this.notify("taskCompleted", task);  
    }  
  }  

  // 观察者模式实现  
  addObserver(callback) {  
    this.observers.push(callback);  
  }  

  notify(event, data) {  
    this.observers.forEach(observer => observer(event, data));  
  }  
}  

// 使用  
const manager = new TaskManager();  
manager.addObserver((event, data) => {  
  console.log(`事件 ${event} 触发,数据:`, data);  
});  

const newTask = TaskManager.createTask("学习 JavaScript 设计");  
manager.addTask(newTask);  
manager.completeTask(newTask.id);  

通过本文的讲解,我们看到 js design 不仅是代码层面的优化,更是一种系统性思维的体现。从基础的设计原则到现代的 ES6 模式,开发者可以通过合理的设计提升代码的可维护性,降低复杂度。在实际项目中,结合设计模式与最佳实践,能够显著提高团队协作效率和代码质量。

未来,随着 JavaScript 生态的持续发展,掌握灵活的设计方法论将愈发重要。建议读者在日常开发中主动实践这些模式,并根据项目需求不断优化自己的设计体系。记住:优秀的 js design 是通往高效、可扩展代码的必经之路。

最新发布