JavaScript设计模式精讲:从构造器到架构实践

217 阅读3分钟

引言

各位同学好!今天我想和大家分享JavaScript中一个非常重要的概念 —— 构造器(Constructor)。

在深入设计模式之前,我们需要先理解构造器这个基础概念,因为它是JavaScript面向对象编程的基石,也是很多设计模式实现的关键。

什么是构造器?

构造器,简单来说就是一个用于创建对象的特殊函数。

在JavaScript中,在想要认识构造器可以从以下几个方面入手

1. 命名规范:它是一个函数,通常首字母大写(这是约定俗成的命名规范)

// 构造器函数名通常首字母大写
function Person(name, age) {
    this.name = name;
    this.age = age;
}

2. 调用方式:使用 new 关键字来调用它

// 使用new关键字调用构造器
const person1 = new Person("张三", 25);
const person2 = new Person("李四", 30);

3. 构造器的作用:可以创建多个具有相同结构但数据不同的对象

function Car(brand, model) {
    // 1. 初始化对象属性
    this.brand = brand;
    this.model = model;
    
    // 2. 可以定义方法
    this.start = function() {
        return `${this.brand} ${this.model} 启动了`;
    }
}

const myCar = new Car("丰田", "凯美瑞");
console.log(myCar.brand);  // 输出: 丰田
console.log(myCar.start()); // 输出: 丰田 凯美瑞 启动了

构造器的核心特点【重点】

  1. 自动创建新对象:使用new关键字时自动创建空对象
  2. this指向:构造器中的this指向新创建的对象
  3. 返回机制:若无显式返回值,自动返回新创建的对象

现代JavaScript中的构造器

ES6 Class语法

class Animal {
    constructor(name) {
        this.name = name;
    }
    
    speak() {
        return `${this.name} 发出声音`;
    }
}

const dog = new Animal("小狗");
console.log(dog.speak()); // 输出: 小狗 发出声音

构造器与原型的关系【拓展】

概念对比

  1. 原型(Prototype)是JavaScript中实现继承和共享属性/方法的重要机制。每个JavaScript对象都有一个原型对象,可以从中继承属性和方法。
  2. 每个构造器函数都有一个特殊的 prototype 属性,通过构造器创建的实例对象都会自动关联到构造器的 prototype,实例对象可以访问原型上定义的所有属性和方法

实现对比:

  • 原型方法定义
// 定义构造器
function Animal(name) {
    this.name = name;
}

// 在原型上添加方法
Animal.prototype.sayName = function() {
    return `我的名字是${this.name}`;
};

const cat = new Animal("小猫");
console.log(cat.sayName()); // 输出:我的名字是小猫
  • 继承实现
// 父类构造器
function Animal(name) {
    this.name = name;
}

Animal.prototype.eat = function() {
    return `${this.name}正在吃东西`;
};

// 子类构造器
function Dog(name, breed) {
    // 调用父类构造器
    Animal.call(this, name);
    this.breed = breed;
}

// 实现原型继承
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 添加子类自己的方法
Dog.prototype.bark = function() {
    return `${this.name}在汪汪叫`;
};

const myDog = new Dog("旺财", "柴犬");
console.log(myDog.eat());  // 输出:旺财正在吃东西
console.log(myDog.bark()); // 输出:旺财在汪汪叫

⚠️需要注意的几点:

  1. 构造器函数如果不使用new调用,this会指向全局对象(在非严格模式下)或undefined(在严格模式下)
  2. 构造器可以配合原型(prototype)使用,实现方法的共享
  3. ES6的class语法本质上还是基于构造器和原型的语法糖
  4. 构造器是实现面向对象编程的重要工具 通过构造器,我们可以创建具有相同结构但不同属性值的多个对象,这是JavaScript中实现面向对象编程的基础。

构造器与类的关系【拓展】

概念对比

  1. 类是完整的蓝图,包含属性和方法的完整定义
  2. 构造器是类中负责初始化对象的特殊方法

实现对比:

// 传统构造器方式
function Person(name) {
    this.name = name;
}

// ES6 类方式
class Person {
    constructor(name) {  // 这里的constructor就是构造器
        this.name = name;
    }
}

构造器只是类中负责初始化对象的特殊方法

// 构造器方式
function Animal(name) {
    this.name = name;
}
// 需要通过原型单独添加方法
Animal.prototype.sayHello = function() {
    console.log(`我是${this.name}`);
}

// 类方式
class Animal {
    constructor(name) {  // 构造器
        this.name = name;
    }
    
    // 可以直接在类中定义方法
    sayHello() {
        console.log(`我是${this.name}`);
    }
}

类提供了更完整的面向对象编程语法

  • 类可以包含构造器、实例方法、静态方法、getter/setter等
  • 类中的构造器使用constructor关键字定义
// 类的方式更加清晰和完整
class Student {
    constructor(name, grade) {  // 构造器部分
        this.name = name;
        this.grade = grade;
    }
    
    study() {  // 类的方法
        return `${this.name}正在学习`;
    }
    
    static createStudent(name) {  // 静态方法
        return new Student(name, 1);
    }
    
    get info() {  // getter
        return `${this.name} - ${this.grade}年级`;
    }
}

总结:构造器和类并不是一致的概念,而是包含与被包含的关系。类是一个更大的概念,而构造器是类中的一个重要组成部分。

结束语

理解构造器对于我们后面学习设计模式非常重要,因为很多设计模式都会用到构造器的概念,比如工厂模式、单例模式等。

接下来,我们将逐步深入探讨JavaScript中的各种设计模式,看看如何运用这些模式来编写更优雅、更可维护的代码。大家准备好了吗?