JavaScript创建对象方式总结【工厂模式、构造函数模式、原型模式等】
本文总结了JavaScript中创建对象的多种方式,包括一般方法、工厂模式、构造函数模式、原型模式以及组合使用构造函数和原型模式。文章详细解析了各模式的优缺点,如工厂模式解决代码重复但无法识别对象类型,构造函数模式解决类型识别但方法重复创建,原型模式实现共享但属性共享可能导致意外修改。最后介绍了动态原型、寄生构造函数和稳妥构造函数模式,帮助开发者根据实际需求选择合适的对象创建方式。
本文汇总了JavaScript中创建对象的多种实现方式,供读者参考学习。
此处主要总结《JavaScript高级程序设计》第六章(面向对象的程序设计)的内容,该章节至少阅读了4遍。本章核心讲解对象的创建与继承机制,其中涉及的创建对象和继承方式至少有6种,结合各类方法与属性,内容繁杂易混淆。因此有必要梳理本章要点,便于日后查阅复习。
受篇幅限制,本文仅聚焦于对象的创建方式。
1 创建对象
1.1 一般方法
可通过Object构造函数或对象字面量语法来创建对象。
var o = {a: 1};
var o2=new Object();
o2.a=1;
这种方式的缺陷在于,若使用同一接口创建大量对象,会导致代码高度重复。
1.2工厂模式
function parent(name,age){
var Child = new Object();
Child.name=name;
Child.age=age;
Child.sayHi=function(){
console.log("Hi");
}
return Child;
};
var x = Parent("Tom",12);
console.log(x.name); //Tom
x.sayHi(); //Hi
函数parent可根据传入的参数构建一个包含所有必要信息的child对象。该函数可被无限次调用,每次均返回一个包含两个属性及一个方法的对象。
此模式解决了创建多个相似对象时的代码重复问题,但未能解决对象识别问题(即无法准确判断一个对象的具体类型)。
1.3构造函数模式
对于“构造函数”这一概念,熟悉Java或C++的读者应当不陌生,在JavaScript中其用法也大致相同。
下面通过构造函数将前述示例重写:
function Parent(name,age){
this.name=name;
this.age=age;
this.sayHi=function(){
console.log("Hi");
};
}
var x = new Parent("Tom",12);
console.log(x.name); //Tom
x.sayHi(); //Hi
调用构造函数时,必须使用关键字 new。需注意,构造函数名称始终以大写字母开头,而非构造函数则以小写字母开头。
与工厂模式相比,构造函数模式主要有以下区别:
- 无需显式创建对象;
- 直接将属性和方法赋值给this对象;
- 省略了
return语句。
构造函数模式的缺点在于,每个方法都必须在每个实例上重新创建一遍。
1.4原型模式
JavaScript中每个函数都拥有一个prototype(原型)属性,该属性是一个指针,指向一个对象。此对象用于包含可由特定类型的所有实例共享的属性和方法。使用原型对象的优势在于,所有对象实例可共享其包含的属性和方法。
function Parent(name,age){
Parent.prototype.name=name;
Parent.prototype.age=age;
Parent.prototype.sayHi=function(){
console.log("Hi");
};
}
var x = new Parent("Tom",12);
console.log(x.name); //Tom
x.sayHi(); //Hi
然而,其优点同时也是缺点,即属性和方法均可被共享。具体表现可参考以下示例:
function Parent(name,age){
Parent.prototype.name=name;
Parent.prototype.age=age;
Parent.prototype.arr=["123","we"];
Parent.prototype.sayHi=function(){
console.log("Hi");
};
}
var x = new Parent("Tom",12);
var y = new Parent("Tom1",12);
x.arr.push("x");
y.arr.push("y");
console.log(x.arr);//["123", "we", "x", "y"]
console.log(y.arr);//["123", "we", "x", "y"]
若对象x修改自己的属性,竟会影响到y对象;反之亦然。这种情形显然不合理,令人担忧。
1.5组合使用构造函数模式和原型模式
function Parent(name,age){
//只把属性留在这里定义,方法放在原型对象中
this.name=name;
this.age=age;
}
//第一种方式
Parent.prototype.sayHi=function(){
console.log("Hi");
};
//第二种方式
//由于采用对象字面量,因此必须修正其constructor属性;
Parent.prototype={
constructor:Parent,
sayHi:function(){
console.log("Hi");
}
}
var x = new Parent("Tom",12);
console.log(x.name); //Tom
x.sayHi(); //Hi
在此示例中,实例属性均在构造函数中定义,而由所有实例共享的属性constructor及方法则在原型中定义。
这是目前使用最广泛、认同度最高的一种创建自定义类型的方法。
--------------------------感觉后面几种方法有些变态了--------------------------------
1.6 动态原型模式
function Parent(name,age){
this.name=name;
this.age=age;
if( typeof this.sayHi !="function"){
Parent.prototype.sayHi=function(){
console.log("Hi");
};
}
}
var x = new Parent("Tom",12);
console.log(x.name); //Tom
x.sayHi(); //Hi
通过检查某个应存在的方法是否有效,来决定是否需要初始化原型。
1.7寄生构造函数模式
当前面几种模式均不适用时,可采用寄生构造函数模式。该模式的基本思想是创建一个函数,其作用仅仅是封装创建对象的代码,随后返回新创建的对象。
function parent(name,age){
var Child = new Object();
Child.name=name;
Child.age=age;
Child.sayHi=function(){
console.log("Hi");
}
return Child;
};
var x = Parent("Tom",12);
console.log(x.name); //Tom
x.sayHi(); //Hi
但实际上,这与工厂模式完全一致,令人困惑。
1.8稳妥构造函数模式
稳妥构造函数遵循与寄生构造函数模式类似的模式,但存在两点不同:一是新创建对象的实例方法不引用this; 二是避免使用new操作调用构造函数。
function Parent(name,age){
var o=new Object();
//私有变量或者方法
var name=name,
age=age;
o.sayName=function(){
//name前面没有this
console.log(name+" "+age)
}
return o;
}
var x = Parent("Tom",12);
x.sayName(); //Tom 12
变量x中保存的是一个稳妥对象,除调用sayName()方法外,无其他途径可访问其数据成员。
更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
