JavaScript 对象创建的六种方式详解
本文系统介绍了 JavaScript 中定义对象的六种主要方式,包括工厂模式、构造函数模式、原型模式、混合构造函数/原型模式、动态原型模式以及混合工厂模式。通过对比各模式的代码实现、内存占用及属性共享机制,重点解析了原型链中引用类型属性的潜在问题,并推荐混合构造函数/原型模式为当前最广泛使用的最佳实践。
在 JavaScript 中,定义类或对象的方式多种多样。
1、工厂方式
工厂方式
function Car(){
var ocar = new Object;
ocar.color = "blue";
ocar.doors = 4;
ocar.showColor = function(){
document.write(this.color)
};
return ocar;
}
var car1 = Car();
var car2 = Car();
调用该函数时会创建新对象,并赋予其所有属性和方法。利用这种方式可以生成两个属性完全相同的对象。当然,也可以通过传递参数来改进这种模式。
function Car(color,door){
var ocar = new Object;
ocar.color = color;
ocar.doors = door;
ocar.showColor = function(){
document.write(this.color)
};
return ocar;
}
var car1 = Car("red",4);
var car2 = Car("blue",4);
car1.showColor() //output:"red"
car2.showColor() //output:"blue"
现在,可以通过向函数传递不同的参数来获取具有不同属性值的对象实例。
在前面的示例中,每次调用 Car() 函数时,都会重新创建 showColor() 方法,这意味着每个对象都拥有自己独立的 showColor() 方法副本。
然而事实上,每个对象本应共享同一个函数逻辑。
虽然可以在函数外部定义方法,然后将函数的属性指向该方法,
function showColor(){
alert(this.color);
}
function Car(){
var ocar = new Object();
ocar.color = color;
ocar.doors = door;
ocar.showColor = showColor;
return ocar;
}
但这种方式在语义上看起来不太像函数的方法。
2、构造函数方式
构造函数方式与工厂方式类似,实现起来同样简单,代码如下:
构造函数方式
function Car(color,door){
this.color = color;
this.doors = door;
this.showColor = function(){
alert(this.color)
};
}
var car1 = new Car("red",4);
var car2 = new Car("blue",4);
可以看到,构造函数方式在函数内部并未显式创建对象,而是使用 this 关键字。因为在调用构造函数时已经创建了对象,所以在函数内部只能通过 this 来访问对象的属性。
现在使用 new 关键字来创建对象,看起来更加规范了!但它与工厂方式存在相同的问题:每次调用构造函数都会为对象创建独立的方法实例。
3、原型方式
该方式利用了对象的 prototype 属性。首先使用一个空函数创建类名,然后将所有的属性和方法都赋予 prototype 属性。
原型方式
function Car(){
}
Car.prototype.color = "red";
Car.prototype.doors = 4;
Car.prototype.showColor = function(){
alert(this.color);
}
var car1 = new Car();
var car2 = new Car();
在这段代码中,首先定义了一个空函数,然后通过 prototype 属性来定义对象的属性。调用该函数时,原型的所有属性都会立即赋予新创建的对象。因此,该函数的所有对象实例存放的都是指向 showColor() 的指针,从语法上看,它们似乎属于同一个对象。
然而,这种函数没有参数,无法通过传递参数来初始化属性,必须在对象创建后才能修改属性的默认值。
原型方式存在一个严重的问题,即当属性指向的是对象(如数组)时。
function Car(){
}
Car.prototype.color = "red";
Car.prototype.doors = 4;
Car.prototype.arr = new Array("a","b");
Car.prototype.showColor = function(){
alert(this.color);
}
var car1 = new Car();
var car2 = new Car();
car1.arr.push("cc");
alert(car1.arr); //output:aa,bb,cc
alert(car2.arr); //output:aa,bb,cc
由于数组是引用类型,Car 的两个对象实例指向的是同一个数组。因此,当在 car1 中添加值后,在 car2 中也能看到该变化。
4、混合的构造函数/原型方式
混合使用构造函数和原型方式,就可以像其他程序设计语言一样创建对象:使用构造函数定义对象的非函数属性,使用原型方式定义对象的方法。
混合构造函数/原型方式
function Car(color,door){
this.color = color;
this.doors = door;
this.arr = new Array("aa","bb");
}
Car.prototype.showColor(){
alert(this.color);
}
var car1 = new Car("red",4);
var car2 = new Car("blue",4);
car1.arr.push("cc");
alert(car1.arr); //output:aa,bb,cc
alert(car2.arr); //output:aa,bb
5、动态原型方式
动态原型方式与混合构造函数/原型方式的原理相似。唯一的区别在于赋予对象方法的位置。
动态原型方式
function Car(color,door){
this.color = color;
this.doors = door;
this.arr = new Array("aa","bb");
if(typeof Car._initialized == "undefined"){
Car.prototype.showColor = function(){
alert(this.color);
};
Car._initialized = true;
}
}
动态原型方式使用一个标志位来判断是否已经给原型赋予了方法。这样可以保证该方法只创建一次。
6、混合工厂方式
它的目的是创建假构造函数,仅返回另一种对象的新实例。
混合工厂方式
function Car(){
var ocar = new Object();
ocar.color = "red";
ocar.doors = 4;
ocar.showColor = function(){
alert(this.color)
};
return ocar;
}
与工厂方式不同的是,这种方式使用了 new 运算符。
以上就是所有的对象创建方法。目前使用最广泛的是混合构造函数/原型方式,此外,动态原型方式也很流行,在功能上与构造函数/原型方式等价。
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
