JavaScript 类(class)(建议收藏)

更新时间:

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

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 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+ 小伙伴加入学习 ,欢迎点击围观

前言

在 JavaScript 的演化历程中,面向对象编程(OOP)始终是开发者关注的核心话题之一。随着 ES6 的引入,JavaScript 通过 类(Class) 语法为开发者提供了更直观、更接近传统面向对象语言的编码体验。本文将从零开始,系统性地解析 JavaScript 类的语法、特性及实际应用场景,帮助编程初学者和中级开发者快速掌握这一重要工具。


类的基本语法:面向对象的“蓝图”

在 JavaScript 中,类(Class) 是一种语法糖(Syntactic Sugar),其底层仍基于原型(Prototype)机制实现。通过类,开发者可以更直观地定义对象的“蓝图”,并创建具有相同属性和方法的实例。

1. 定义一个类

使用 class 关键字定义类,类名通常遵循大驼峰命名法(PascalCase)。例如,定义一个 Person 类:

class Person {
  // 类的构造函数(Constructor)
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  // 实例方法
  greet() {
    return `Hello, my name is ${this.name} and I'm ${this.age} years old.`;
  }
}

比喻解释
类可以想象为一个“工厂蓝图”。Person 类就像工厂的设计图纸,而 constructor 是生产线上的组装流程,负责初始化每个实例的属性。greet() 方法则是产品出厂后具备的功能。

2. 创建类的实例

通过 new 关键字调用类的构造函数,生成实例对象:

const alice = new Person("Alice", 30);
console.log(alice.greet()); // 输出:Hello, my name is Alice and I'm 30 years old.

3. 类的属性与方法

类支持定义两种类型的方法:

  • 实例方法:通过 this 关键词访问实例属性,如上述的 greet() 方法。
  • 静态方法:通过 static 关键字声明,属于类本身而非实例,常用于工具函数或类级别的操作:
class MathUtil {
  static add(a, b) {
    return a + b;
  }
}

console.log(MathUtil.add(2, 3)); // 输出:5

继承:类的“家族树”

继承是面向对象编程的核心特性之一。通过 extends 关键字,一个类可以继承另一个类(父类/超类)的属性和方法。

1. 定义子类

class Student extends Person {
  constructor(name, age, grade) {
    // 必须调用父类的 constructor
    super(name, age);
    this.grade = grade;
  }

  study(subject) {
    return `${this.name} is studying ${subject} in grade ${this.grade}.`;
  }
}

比喻解释
继承如同生物学中的物种演化。Student 类继承了 Person 的属性(nameage)和方法(greet()),并在此基础上新增了 grade 属性和 study() 方法。

2. 覆写父类方法

子类可以通过重写方法实现多态性:

class Teacher extends Person {
  constructor(name, age, subject) {
    super(name, age);
    this.subject = subject;
  }

  // 覆写 greet() 方法
  greet() {
    return `${super.greet()} I teach ${this.subject}.`;
  }
}

const mrSmith = new Teacher("Mr. Smith", 45, "Math");
console.log(mrSmith.greet()); // 输出:Hello... I teach Math.

高级特性:静态方法与私有字段

1. 静态方法的实用场景

静态方法常用于无需实例即可执行的操作,例如数据验证或工具函数:

class Validator {
  static isEmail(email) {
    // 简单的邮箱格式验证
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  }
}

console.log(Validator.isEmail("test@example.com")); // true

2. 私有字段:封装数据的“保险箱”

ES2022 引入了类的私有字段(Private Fields),通过 # 符号前缀声明。私有字段仅在类内部可访问,确保数据封装性:

class BankAccount {
  #balance = 0;

  deposit(amount) {
    this.#balance += amount;
  }

  withdraw(amount) {
    if (amount <= this.#balance) {
      this.#balance -= amount;
      return true;
    }
    return false;
  }
}

const account = new BankAccount();
account.deposit(100);
// 尝试直接访问私有字段会报错:account.#balance // 报错!

实战案例:构建电商购物车

案例需求

假设需要实现一个简单的购物车系统,包含以下功能:

  1. 添加商品到购物车
  2. 计算总价
  3. 清空购物车

实现代码

class Product {
  #price;
  constructor(name, price) {
    this.name = name;
    this.#price = price;
  }

  getPrice() {
    return this.#price;
  }
}

class ShoppingCart {
  constructor() {
    this.items = [];
  }

  addItem(product) {
    this.items.push(product);
  }

  calculateTotal() {
    return this.items.reduce(
      (total, item) => total + item.getPrice(),
      0
    );
  }

  clear() {
    this.items = [];
    console.log("Cart cleared.");
  }
}

// 使用示例
const laptop = new Product("Laptop", 1000);
const phone = new Product("Phone", 500);

const cart = new ShoppingCart();
cart.addItem(laptop);
cart.addItem(phone);

console.log(`Total: $${cart.calculateTotal()}`); // 输出:Total: $1500
cart.clear(); // 输出:Cart cleared.

案例解析

  • Product 类:使用私有字段 #price 确保价格不可被外部直接修改。
  • ShoppingCart 类:通过 addItem()calculateTotal() 等方法实现购物车的核心功能。
  • 继承与组合:此处未直接使用继承,而是通过组合(Composition)的方式复用 Product 类的功能,体现了面向对象设计的灵活性。

类与函数式编程的平衡

虽然 JavaScript 的类语法简化了面向对象的开发,但现代代码设计常结合函数式编程(FP)原则。例如,避免过度依赖类的继承层级,转而使用高阶函数或工厂模式:

// 工厂函数替代简单类
function createProduct(name, price) {
  return {
    name,
    price,
    getPrice: () => price,
  };
}

// 使用工厂函数创建对象
const book = createProduct("JavaScript Guide", 25);

选择建议

  • 使用类:当需要复杂的继承关系、状态管理或封装时(如 UI 组件、复杂业务模型)。
  • 使用函数或对象字面量:对于简单数据结构或无需继承的场景,以保持代码简洁性。

结论

JavaScript 类通过直观的语法和强大的特性,为开发者提供了构建可维护、可扩展代码的强大工具。从基础语法到继承、私有字段,再到实际项目中的应用,类的掌握程度直接影响代码的组织能力和面向对象思维的深度。

无论是电商系统的购物车、游戏中的角色管理,还是复杂的业务逻辑建模,合理运用类都能显著提升代码的可读性和复用性。建议读者通过实际项目不断练习,并结合函数式编程思想,找到最适合场景的解决方案。

掌握 JavaScript 类,不仅是技术能力的提升,更是面向对象思维的系统性进阶。希望本文能成为你学习旅程中的一个坚实阶梯!

最新发布