JavaScript 创建对象的五种常见模式详解
本文详细解析JavaScript中创建对象的五种核心模式:工厂模式、构造函数模式、原型模式、混合模式以及动态原型模式。通过对比各模式的代码实现、内存占用及适用场景,帮助开发者理解如何根据需求选择最优的对象创建方案,并掌握原型链与this指向的关键机制。
JavaScript对象创建概述
首先展示一段基础代码示例:
function O(user,pwd){ //use constructor
this.user=user;
this.pwd=pwd;
this.get=get;
return this;
}
function O2(user,pwd){ //use factory
var obj=new Object();
obj.user=user;
obj.pwd=pwd;
obj.get=get;
return obj;
}
function O3(){ //use prototype
}
O3.prototype.user='abc';
O3.prototype.pwd='dis';
// O3.propotype.get='get';
//O3.prototype.get(){
//alert(this.pwd);
//}
function O4(user,pwd){
this.user=user;
this.pwd=pwd;
return this;
}
O4.prototype.get=function(){alert('123');}
//function get(){
//alert("This User:"+this.user);
// }
function test2(){
//var a=new O2('Us','Pw'); use factory & constructor
//var a=new O3(); //use prototype
//a.get();
var a=new O4('*U4','P4'); //混合
//a.user='Not ABC'; //set new property
//alert(a.user);
a.get();
}
常用的方法大致就这几种,可能还有其他变体,遇到时再行探讨。
题外话:昨天尝试用alert(window.appName)在Firefox中查看浏览器版本,结果弹出的是Netscape,而非Firefox。随后在Chrome下试验,同样弹出Netscape。百度搜索Netscape后发现JavaScript源自Netscape公司。深感惭愧,研究JS许久却不知其祖师爷。查阅族谱发现JS由Brendan Eich创造,95年他创造JS时年仅31岁。真是人比人气死人,如他一般老的我,到现在都学不会js,真是人比人气死人。。js当初设计的时候,没有想到自己能从一部打电话用的手机变成集拍照,上网,游戏,电话于一身的智能机。真是造化弄人!!!也许各中的神奇,连Brendan Eich本人都没有想到。应该说Brendan Eich创造了js,而一大批的js牛人成就了今天如此复杂的js。
js不是木有类么?没关系,人家不是设计了原型属性么~
js不是木有块级作用域么?没关系,人家不是有作用域链么~
js怎样实现成员变量私有化?哦,用闭包解决吧~
哦,这么多基本概念,彻底的晕掉了,路漫漫其修远兮。
工厂模式与构造函数模式
言归正传,本文讨论几种js创建对象的方法,先从最好理解的工厂模式开始:
代码如下:
function createPerson(name,age,job){
var o = {};
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var tanya = createPerson("tanya","30","female");
var ansel = createPerson("ansel","30","male");
tanya.sayName();
ansel.sayName(); 这里先定义o为一个空的对象,然后为o设置了一堆属性。其实也可以直接给o属性的嘛,所以如果这样写也是ok的。
代码如下:
function createPerson(name,age,job){
var o = {
name : name,
age : age,
job : job,
sayName : function(){
alert(this.name);
}
};
return o;
}
var tanya = createPerson("tanya","30","female");
var ansel = createPerson("ansel","30","male");
tanya.sayName();
ansel.sayName(); 构造函数模式的深入应用
还有一种办法是利用无敌的this,因为this就表示当前运行时的对象,将构造函数this的作用域指向新对象,将当前运行对象的属性和方法都赋给新对象,这样对象模式称为构造函数模式
代码如下:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var tanya = new Person("tanya","30","female");
var ansel = new Person("ansel","30","male");
tanya.sayName();
ansel.sayName(); 在这个例子中,tanya和ansel都有一个constructor属性,该属性指向person。
考虑一下如下的情况:
代码如下:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
Person("tanya","30","female");
Person("ansel","30","male");
window.sayName();
window.sayName(); 发现两次弹出的都是ansel,这是因为不用new的话,就不是一个person的实例,而仅仅在执行函数。而在全局作用域调用一个函数时this总是指向Global对象。而Global对象在浏览器中就是window对象。
我们还可以用构造模式在另外一个对象中调用sayName方法,还记得Apply和call么,来吧再考虑另外一种情况,
代码如下:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var olivia = {};
Person.call(olivia,"tanya","30","female");
olivia.sayName();
var philip = {}
Person.apply(philip,["ansel","30","male"]);
philip.sayName(); 原型模式与混合模式
原型模式就要考虑原型链了,分析一下,sayName方法在实例中被重复定义了两次,但其实没有必要创造两个一样的副本。使用原型方法,可以使是tanya和ansel的共享一个sayName方法。
于是原型模式的写法如下:
代码如下:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype.sayName= function(){
alert(this.name);
};
var tanya = new Person("tanya","30","female");
var ansel = new Person("ansel","30","male");
tanya.sayName();
ansel.sayName(); 实际应用时,不是一成不变的套用某种模式,活学活用。需要共享方法的时候就用原型模式,需要使用副本的时候就用构造模式,还可以结合起来,把所有信息都封装在构造函数中,而通过在构造函数中初始化原型,使得对象保持了同时使用构造函数和原型的优点。
代码如下:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
if (typeof sayName != "function" ){
Person.prototype.sayName= function(){
alert(this.name);
};
}
}
var tanya = new Person("tanya","30","female");
var ansel = new Person("ansel","30","male");
ansel.sayName = function () {
alert("Hi ansel, how hansome you are!");
}
tanya.sayName();
ansel.sayName();什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
