JavaScript 创建对象的三种常用设计模式:工厂、构造函数与原型
本文深入解析 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创建对象设计模式的资料请关注本站其它相关文章!
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
