JavaScript 创建对象的三种常用设计模式:工厂、构造函数与原型

作者:异步漫步时间:2026-10-25 14:51:58浏览:197

本文深入解析 JavaScript 中创建对象的三种核心设计模式:工厂模式、构造函数模式和原型模式。通过代码示例对比它们的实现差异,重点剖析 new 关键字的执行步骤、原型链机制以及引用值共享带来的潜在问题,帮助开发者根据实际需求选择最合适的对象创建方案。

引言

许多开发者认为设计模式在实际工作中鲜少使用,但实际上它们无处不在,正如王国维所言:众里寻他千百度,蓦然回首,那人正在灯火阑珊处。

工厂模式

从字面理解,工厂模式类似于现实生活中的市场机制,由不同的工厂加工生产各类产品。

将其转化为 JavaScript 代码,实现方式如下:

// 汽车工厂
function carFactory(brand, price, district) {
	 let o = new Object();
	 o.brand= brand;
	 o.price= price;
	 o.district= district;
	 o.performance= function() {
		 console.log(this.brand);
	 };
	 return o;
}
// 生产汽车
let car1 = carFactory("Benz", 50, "china");
let car2= carFactory("Honda", 30, "usa");
// 糖果工厂
function candyFactory(name, size, color) {
	 let o = new Object();
	 o.name= name;
	 o.size= size;
	 o.color= color;
	 o.performance= function() {
		 console.log(this.name);
	 };
	 return o;
}
// 生产糖果
let candy1= candyFactory("Oreo", "small", "white");
let candy2= candyFactory("quduoduo", "middle", "black");

例如汽车工厂和糖果工厂,通过工厂函数我们可以创建出具有特定属性的对象。

工厂模式是一种广为人知的设计模式,在软件工程领域被广泛运用,旨在抽象化特定对象的创建过程。

构造函数模式

构造函数专门用于创建特定类型的对象,开发者可以自定义构造函数,以函数形式为对象类型定义属性和方法。

以前面的例子为例,可以改写为:

// 构造汽车的构造函数
function Car(brand, price, district) {
	 this.brand= brand;
	 this.price= price;
	 this.district= district;
	 this.performance= function() {
		 console.log(this.brand);
	 };
}
// 构造汽车
let car1 = new Car("Benz", 50, "china");
let car2= new Car("Honda", 30, "usa");

与工厂模式相比,构造函数模式具有以下区别:

  • 不显式创建对象
  • 属性和方法直接赋值给 this
  • 没有 return 语句

构造函数名称首字母通常大写

这里涉及一个关键考点:使用 new 关键字时会发生什么?

官方解释如下:

1. 在内存中创建一个新对象。2. 该新对象内部的 [[Prototype]](隐式原型)特性被赋值为构造函数的 prototype(显示原型)属性。3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。4. 执行构造函数内部的代码(为新对象添加属性)。5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

这就是“原型链”的构建过程。

car1.__proto__===Car.prototype // true
car1 instanceof Car // true
  • 构造函数的主要问题在于,其定义的方法会在每个实例上重新创建一遍。

具体含义可通过代码解释:

即使方法逻辑相同,它们也不相等,因为每次执行 new 时,实例的方法都是重新创建的;

// 构造汽车的构造函数
function Car(brand, price, district) {
	 this.brand= brand;
	 this.price= price;
	 this.district= district;
	 this.performance= function() {
	 };
}
// 构造汽车
let car1 = new Car("Benz", 50, "china");
let car2= new Car("Honda", 30, "usa");
car1.performance == car2.performance // false

原型模式

原型模式旨在解决构造函数模式中“重复创建方法”的问题。

在此不妨重温一下原型链的指向关系:

// 原型创建
function Car(brand, price, district) {
	 Car.prototype.brand= brand;
	 Car.prototype.price= price;
	 Car.prototype.district= district;
	 Car.prototype.performance= function() {
	 };
}
let car1 = new Car("Benz", 50, "china");
let car2= new Car("Honda", 30, "usa");
car1.performance === car2.performance // true

原型模式弱化了向构造函数传递初始化参数的能力,导致所有实例默认取得相同的属性值。

car1.__proto__===Car.prototype // true
Car.__proto__===Function.prototype // true
Function.prototype.__proto__===Object.prototype //true
Car.prototype.__proto__===Object.prototype //true
Object.prototype.__proto__===null // true

原型上的所有属性在实例间共享,这对函数来说比较合适。对于原始值的属性也还好,但对于引用值的属性,则会产生混乱。

function Person() {}
Person.prototype = {
 constructor: Person,
 friends: "A",
 sayName() {
 }
}; 
let person1 = new Person();
let person2 = new Person();
person1.friends="B";
person1.friends // 'B'
person2.friends // 'A'
function PersonArr() {}
PersonArr.prototype = {
 constructor: PersonArr,
 friends:["A"],
 sayName() {
 }
}; 
let person1 = new PersonArr();
let person2 = new PersonArr();
person1.friends.push("B");
person1.friends // ["A","B"]
person2.friends // ["A","B"]

结语

工厂模式、构造函数模式和原型模式没有绝对的优劣之分,使用时更讲究“适合”。只有清楚它们的原理,才能游刃有余。

更多关于 JS 创建对象设计模式的资料请关注本站其它相关文章!

更多关于JS创建对象设计模式的资料请关注本站其它相关文章!

作者最新文章