JavaScript 七种对象创建模式详解与对比
本文系统梳理了 JavaScript 中七种常见的对象创建模式,包括工厂模式、构造函数模式、原型模式、组合模式、动态原型模式、寄生构造函数模式及稳妥构造函数模式。详细解析了各模式的实现原理、优缺点及适用场景,重点探讨了原型链继承中的引用类型共享问题与构造函数优化方案,为开发者提供清晰的选型参考。
引言与背景
本文旨在整理并记录多种设计模式的优缺点,以便后续查阅与回顾。
半年前阅读《JavaScript 高级程序设计》时,对设计模式章节感到困惑,并非无法理解语法,而是质疑为何创建对象需要如此复杂的流程。近期完成首个小型项目后,深刻体会到代码量激增时缺乏规范与约束带来的混乱。因此,重新研读相关章节,总结几种常用设计模式的优劣。
本文将介绍七种设计模式,涵盖其应用场景及各自的优势与劣势。
工厂模式与构造函数模式
1. 工厂模式
通过函数封装对象创建逻辑,并直接返回对象实例。
function person (name,age) {
var obj=new Object();
obj.name=name;
obj.age=age;
obj.sayName=function () {
alert(this.name);
};
return obj;
}
var me=person("Su",25);
缺点:无法识别对象的具体类型,所有创建出的对象均被视为 Object 的实例,难以进行区分。
原型模式与组合模式
2. 构造函数模式
function Person (name,age) {
this.name=name;
this.age=age;
this.sayName=function () {
alert(this.name);
};
}
var me=new Person("Su",25);
优点:利用构造函数可以将实例明确标识为特定类型。
缺点:在构造函数内部定义的方法会导致每个实例都创建独立的方法副本,若仅需公用方法,会造成不必要的性能浪费。
3. 原型模式
基于原型链实现继承。
function Person () {}
Person.prototype.name="Su";
Person.prototype.sayName=function () {
alert(this.name);}
var me =new Person();
缺点:所有属性和方法被实例共享。当属性或方法中包含引用类型值时,修改一个实例的属性或方法会影响其他所有实例。
4. 原型与构造函数组合模式
私有属性和方法通过构造函数定义,公有属性和方法通过原型继承,融合了两种方法的优点。
function Person (name,age) {
this.name=name;
this.age=age;
}
Person.prototype={
constructor:Person,
sayName:function () {
alert(this.name);
}
}
var me=new Person("Su",25);
缺点:需注意引用类型值在原型继承中的共享问题。
注:上述代码重写了 Person 构造函数的原型对象,将原型指针指向一个新对象,导致 constructor 属性指向 Object 而非 Person,因此需显式将其重置为 Person。
动态原型与寄生构造函数模式
5. 动态原型模式
本质上仍为构造函数,仅在指定方法不存在时,向原型对象中添加该方法。
function Person (name,age) {
this.name=name;
this.age=age;
if (typeof this.sayName!="function") {
Person.prototype.sayName=function () {
alert(this.name);
}
}
}
var me =new Person("Su",25);
缺点:不能使用对象字面量重写原型对象,因为这会使实例指针指向新的原型对象,导致在原型中添加的方法(如 sayName)失效。
6. 寄生构造函数模式
调用时使用 new 操作符,除此之外与工厂模式无明显区别,欢迎指正。
function person (name,age) {
var obj=new Object();
obj.name=name;
obj.age=age;
obj.sayName=function () {
alert(this.name);
};
return obj;
}
var me=new person("Su",25); //这里使用new操作符
稳妥构造函数模式
7. 稳妥构造函数模式
不创建公共属性,禁用 this,仅暴露必要的 API 用于数据访问,适用于对安全性有较高要求的场景。
function Person (name) {
var o=new Object();
o.sayName=function () {
alert(name);
}
return o;
}
var me=Person("Su");
如代码所示,只能通过 sayName 方法访问内部 name 属性。
总结
本文介绍了七种设计模式及其优缺点,希望对学习 JavaScript 设计模式的读者有所帮助。
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
