JavaScript 类(class) constructor() 方法(完整教程)

JavaScript 类(class) constructor() 方法:从零开始理解构造函数的真正作用

在学习 JavaScript 的面向对象编程时,class 语法的出现让代码结构更清晰,逻辑更易维护。而其中最核心、最常被使用的方法之一,就是 constructor() 方法。它不仅是类的“启动按钮”,更是对象初始化的唯一入口。

如果你刚开始接触类的概念,可能会觉得 constructor() 看起来像普通函数,但它其实承担着特殊使命。这篇文章,就带你一步步揭开它的面纱。


什么是 constructor() 方法?

在 JavaScript 中,class 是一种语法糖,它让开发者可以用更接近传统面向对象语言的方式编写代码。而 constructor() 方法,是每个类中必须存在的特殊方法,它在创建类的实例时自动执行。

想象一下,你正在建造一座房子。class 就是房子的设计图纸,而 constructor() 就是开工的第一步——打地基、搭框架。没有这一步,房子就无法真正“诞生”。

class Car {
  // constructor() 是构造函数,会在 new Car() 时自动调用
  constructor(brand, color) {
    // 初始化实例属性
    this.brand = brand;  // 设置品牌
    this.color = color;  // 设置颜色
    this.isRunning = false;  // 默认未启动
  }
}

// 创建一个 Car 实例
const myCar = new Car("丰田", "红色");
console.log(myCar); // { brand: "丰田", color: "红色", isRunning: false }

📌 注释说明:

  • new Car("丰田", "红色") 会自动触发 constructor()
  • this 指向新创建的实例对象,用于设置其属性。
  • constructor() 中的参数 brandcolor 会被赋值给 this.brandthis.color

constructor() 方法的执行时机与角色

constructor() 的最大特点就是自动调用。每当使用 new 关键字创建一个类的实例时,JavaScript 引擎会立即执行 constructor() 方法。

这个过程就像“组装流水线”:

  1. 分配内存空间
  2. 调用 constructor() 初始化属性
  3. 返回新对象
class Person {
  constructor(name, age) {
    console.log(`正在为 ${name} 创建实例...`);  // 执行日志
    this.name = name;
    this.age = age;
    this.hobbies = [];  // 每个实例都有一份独立的数组
  }

  introduce() {
    return `你好,我是 ${this.name},今年 ${this.age} 岁。`;
  }
}

// 创建两个不同实例
const person1 = new Person("小明", 20);
// 输出:正在为 小明 创建实例...

const person2 = new Person("小红", 22);
// 输出:正在为 小红 创建实例...

console.log(person1.introduce()); // 你好,我是 小明,今年 20 岁。
console.log(person2.introduce()); // 你好,我是 小红,今年 22 岁。

📌 注释说明:

  • 每次 new Person() 都会触发一次 constructor(),确保每个对象独立初始化。
  • this.hobbies = [] 是关键:避免多个实例共享同一个数组引用。

constructor() 方法可以接受多个参数,支持默认值

constructor() 并不限制参数数量,你完全可以传入多个参数,甚至设置默认值,提升代码的灵活性。

class BankAccount {
  constructor(owner, initialBalance = 0, accountType = "储蓄账户") {
    this.owner = owner;
    this.balance = initialBalance;
    this.accountType = accountType;
    this.transactionHistory = [];
  }

  deposit(amount) {
    if (amount > 0) {
      this.balance += amount;
      this.transactionHistory.push(`存款: +${amount}`);
    }
  }

  withdraw(amount) {
    if (amount > 0 && amount <= this.balance) {
      this.balance -= amount;
      this.transactionHistory.push(`取款: -${amount}`);
    }
  }

  getBalance() {
    return this.balance;
  }
}

// 使用不同参数创建账户
const account1 = new BankAccount("张三");
// 等价于:new BankAccount("张三", 0, "储蓄账户")

const account2 = new BankAccount("李四", 5000, "信用卡账户");

console.log(account1.balance); // 0
console.log(account2.balance); // 5000
console.log(account2.accountType); // 信用卡账户

📌 注释说明:

  • initialBalance = 0accountType = "储蓄账户" 是默认参数,未传入时自动使用默认值。
  • 这种设计让接口更友好,减少调用者出错概率。

constructor() 方法可以调用其他方法(或执行复杂逻辑)

constructor() 并非只能“赋值”,它也可以包含任意逻辑,比如验证、初始化数据结构、绑定事件等。

class TodoList {
  constructor(title = "待办事项") {
    this.title = title;
    this.items = [];
    this.completedCount = 0;

    // 在构造函数中自动添加初始项目
    this.addItem("学习 JavaScript");
    this.addItem("写博客");
  }

  addItem(text) {
    this.items.push({
      id: Date.now(),  // 用时间戳模拟唯一 ID
      text,
      completed: false
    });
  }

  markComplete(id) {
    const item = this.items.find(item => item.id === id);
    if (item) {
      item.completed = true;
      this.completedCount++;
    }
  }

  getProgress() {
    return this.completedCount / this.items.length;
  }
}

const todo = new TodoList("每日计划");
console.log(todo.items.length); // 2,因为构造函数中添加了两个项目
console.log(todo.getProgress()); // 0,因为都没完成

📌 注释说明:

  • this.addItem("学习 JavaScript") 是在 constructor() 中调用的方法。
  • 通过这种方式,可以确保每个实例在创建时就拥有“默认数据”。
  • 这种模式在构建组件、表单、状态管理时非常实用。

与传统函数构造器的对比:为什么推荐使用 class 和 constructor()

在 ES6 之前,JavaScript 没有 class 语法,开发者通过函数模拟类的行为,比如:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.introduce = function() {
  return `我是 ${this.name},${this.age} 岁。`;
};

const p = new Person("小王", 25);

虽然能实现,但代码不够直观,结构混乱。而使用 classconstructor() 后,逻辑更清晰:

  • constructor() 明确表示“初始化”阶段
  • 属性和方法组织在类体内,一目了然
  • 支持继承、静态方法、访问器等高级特性
// ✅ 推荐写法:使用 class 和 constructor()
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  introduce() {
    return `我是 ${this.name},${this.age} 岁。`;
  }
}

📌 注释说明:

  • class 语法更接近其他语言(如 Java、Python),降低了学习成本。
  • constructor()class 语法中不可或缺的一部分,是实例化对象的“入口”。

常见误区与最佳实践

❌ 误区 1:constructor() 可以返回值

class Test {
  constructor() {
    return { message: "我返回了!" }; // ❌ 无效,构造函数不能返回非对象
  }
}

const t = new Test();
console.log(t); // 输出的是 Test 实例,不是你返回的对象

✅ 正确做法:constructor() 必须返回 this,不能返回其他值。如果返回非对象,会被忽略。

✅ 最佳实践:合理使用默认参数

class Config {
  constructor(options = {}) {
    this.debug = options.debug ?? false;
    this.timeout = options.timeout ?? 5000;
    this.retry = options.retry ?? 3;
  }
}

使用 ?? 操作符可以更安全地处理 undefined,避免误判。


总结:constructor() 是类的“出生证明”

JavaScript 类(class) constructor() 方法 是类实例化过程的核心。它不仅是初始化属性的地方,更是定义对象初始状态的“第一道工序”。

通过本文的讲解,你应该已经明白:

  • constructor()new 时自动执行
  • 它负责设置实例属性,是对象的“出生证明”
  • 支持默认参数、复杂逻辑、方法调用
  • 比传统函数构造器更清晰、更现代

当你编写一个类时,不妨先问自己:“这个对象刚出生时,应该具备哪些属性?” 答案,就藏在 constructor() 里。

记住:构造函数不是可有可无的,而是类存在的意义所在。 从今天起,善用 constructor(),让你的代码更有结构、更易维护。