您现在的位置是:网站首页 > 构造器模式(Constructor)与传统类的区别文章详情

构造器模式(Constructor)与传统类的区别

构造器模式(Constructor)与传统类的区别

构造器模式是JavaScript中创建对象的一种方式,它利用函数作为对象的构造器。传统类则是ES6引入的语法糖,基于原型继承但提供了更接近传统面向对象语言的写法。两者在实现对象创建和继承时存在显著差异。

基本语法对比

构造器模式使用普通函数作为构造器,通过new关键字实例化对象:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    return `Hello, I'm ${this.name}`;
  };
}

const john = new Person('John', 30);

传统类使用class关键字定义:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  greet() {
    return `Hello, I'm ${this.name}`;
  }
}

const john = new Person('John', 30);

原型继承机制

构造器模式显式操作原型链:

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  return `${this.name} makes a noise`;
};

function Dog(name) {
  Animal.call(this, name);
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.speak = function() {
  return `${this.name} barks`;
};

类继承使用extends关键字简化了原型链操作:

class Animal {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    return `${this.name} makes a noise`;
  }
}

class Dog extends Animal {
  speak() {
    return `${this.name} barks`;
  }
}

方法定义差异

构造器模式中方法可以定义在构造函数内部(实例方法)或原型上:

// 实例方法 - 每个实例都有独立副本
function Car(model) {
  this.model = model;
  this.start = function() {
    return `${this.model} starts`;
  };
}

// 原型方法 - 所有实例共享
Car.prototype.stop = function() {
  return `${this.model} stops`;
};

类语法将所有方法默认定义在原型上:

class Car {
  constructor(model) {
    this.model = model;
  }
  
  start() {
    return `${this.model} starts`;
  }
  
  stop() {
    return `${this.model} stops`;
  }
}

静态成员实现

构造器模式通过直接给构造函数添加属性实现静态成员:

function MathUtils() {}

MathUtils.PI = 3.14159;
MathUtils.sum = function(a, b) {
  return a + b;
};

类语法使用static关键字声明静态成员:

class MathUtils {
  static PI = 3.14159;
  
  static sum(a, b) {
    return a + b;
  }
}

私有成员模拟

构造器模式使用闭包模拟私有成员:

function Counter() {
  let count = 0; // 私有变量
  
  this.increment = function() {
    return ++count;
  };
  
  this.getCount = function() {
    return count;
  };
}

类语法可以使用WeakMap或Symbol实现类似效果:

const _count = new WeakMap();

class Counter {
  constructor() {
    _count.set(this, 0);
  }
  
  increment() {
    let count = _count.get(this);
    _count.set(this, ++count);
    return count;
  }
  
  get count() {
    return _count.get(this);
  }
}

提升行为差异

构造器函数会提升到作用域顶部:

const p = new Person('John'); // 可以正常执行

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

类声明不会提升:

const p = new Person('John'); // ReferenceError

class Person {
  constructor(name) {
    this.name = name;
  }
}

类型检查方式

构造器模式使用instanceof检查原型链:

function Vehicle() {}
function Car() {}
Car.prototype = Object.create(Vehicle.prototype);

const myCar = new Car();
console.log(myCar instanceof Vehicle); // true

类继承同样使用instanceof但语法更直观:

class Vehicle {}
class Car extends Vehicle {}

const myCar = new Car();
console.log(myCar instanceof Vehicle); // true

方法枚举性

构造器模式原型上的方法默认可枚举:

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

Person.prototype.greet = function() {
  return `Hello, ${this.name}`;
};

const john = new Person('John');
console.log(Object.keys(john)); // ['name']
for (let key in john) {
  console.log(key); // 'name', 'greet'
}

类方法默认不可枚举:

class Person {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    return `Hello, ${this.name}`;
  }
}

const john = new Person('John');
console.log(Object.keys(john)); // ['name']
for (let key in john) {
  console.log(key); // 'name'
}

构造函数调用限制

构造器函数可以不使用new调用,但可能导致问题:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

const p1 = new Point(1, 2); // 正确
const p2 = Point(3, 4); // 错误,this指向全局对象

类构造器必须使用new调用:

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

const p1 = new Point(1, 2); // 正确
const p2 = Point(3, 4); // TypeError

原型属性访问

构造器模式可以直接访问和修改原型:

function Person() {}
Person.prototype.species = 'Human';

console.log(Person.prototype); // { species: 'Human', constructor: ƒ }

类语法通过访问器属性prototype间接访问:

class Person {
  static get species() {
    return 'Human';
  }
}

console.log(Person.prototype); // Person {}

多构造函数支持

构造器模式可以轻松实现多个构造函数:

function Circle(radius) {
  this.radius = radius;
}

function Rectangle(width, height) {
  this.width = width;
  this.height = height;
}

function createShape(type, ...args) {
  const constructors = { Circle, Rectangle };
  return new constructors[type](...args);
}

类语法需要额外处理:

class Circle {
  constructor(radius) {
    this.radius = radius;
  }
}

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }
}

function createShape(type, ...args) {
  const classes = { Circle, Rectangle };
  return new classes[type](...args);
}

性能考量

构造器模式在方法定义上可能产生更多内存消耗:

function Person(name) {
  this.name = name;
  this.sayName = function() {
    console.log(this.name);
  }; // 每个实例都会创建新函数
}

类方法共享原型上的函数:

class Person {
  constructor(name) {
    this.name = name;
  }
  
  sayName() {
    console.log(this.name);
  } // 所有实例共享同一函数
}

设计模式应用

构造器模式常用于实现工厂模式:

function createEmployee(type) {
  switch(type) {
    case 'manager':
      return new Manager();
    case 'developer':
      return new Developer();
    default:
      throw new Error('Unknown employee type');
  }
}

类语法可以与静态工厂方法结合:

class Employee {
  static create(type) {
    switch(type) {
      case 'manager':
        return new Manager();
      case 'developer':
        return new Developer();
      default:
        throw new Error('Unknown employee type');
    }
  }
}

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步