本文深入解析JavaScript中创建对象的七种主要模式,包括工厂模式、构造函数模式、原型模式及其优缺点。重点探讨如何解决对象识别与方法复用问题,并详细介绍组合使用构造函数和原型模式、动态原型模式、寄生及稳妥构造函数模式,帮助开发者根据场景选择最优方案。
工厂模式
一、工厂模式
function person (name,age) {
var p=new Object();
p.name=name;
p.age=age;
p.showMessage=function(){
console.log("name:"+this.name+" age:"+this.age);
}
return p;
}
var p1=person("k1",28);
var p2=person("k2",29);
console.log(p1.showMessage==p2.showMessage);//false 不是同一个showMessage方法
console.log(p1.constructor);//[object] 都是object
该模式的主要缺陷在于无法解决对象识别问题,且每个实例的 showMessage 方法都是独立创建的,导致内存开销增加。
构造函数模式
二、构造函数模式
function Person (name,age) {
this.name=name;
this.age=age;
this.showMessage=function(){
console.log("name:"+this.name+" age:"+this.age);
}
}
var p1=new Person("k1",28);
var p2=new Person("k2",29);
console.log(p1.showMessage==p2.showMessage);//false 不是同一个showMessage方法
console.log(p1.constructor);//[Person]
console.log(p1 instanceof Person);// true
此模式解决了对象识别问题,但每个实例的 showMessage 方法依然各自独立,存在重复创建带来的性能开销。
原型模式
三、原型模式
function Person () {
}
Person.prototype.name ="k";
Person.prototype.age =29;
Person.prototype.showMessage=function () {
console.log("name:"+this.name+" age:"+this.age);
};
var p1=new Person();
p1.showMessage();//name:k age:29
var p2=new Person();
p2.showMessage();//name:k age:29
console.log(p1.showMessage==p2.showMessage);// true --引用的是同一函数
console.log(p1.constructor)//[Person] --对象识别
console.log(p1 instanceof Person)//true --对象识别
console.log(Person.prototype.isPrototypeOf(p1));// true
console.log(Object.getPrototypeOf(p1)==Person.prototype);// true
原型模式成功解决了方法重复创建的问题,同时也实现了对象识别。
然而,原型模式存在显著缺陷:挂载在 prototype 上的所有属性、变量和函数被所有实例共享。虽然可以通过实例 p1、p2 访问 prototype 的属性,但无法直接修改属性值。例如执行 p1.name="k1" 时,仅在 p1 实例上新增 name 属性,并未修改 prototype.name。对于值类型影响不大,但引用类型会引发问题,具体见如下示例。
function Person () {
};
Person.prototype.age =10;
Person.prototype.array=[1,2,3];
var p1=new Person();
var p2=new Person();
console.log(p1.array);// [1,2,3]
console.log(p2.array); //[1,2,3]
p1.array.push(4);
console.log(p1.array);//[1,2,3,4]
console.log(p2.array);//[1,2,3,4]
当 p1 向 array 添加值时,p2 也会反映该变化,因为两者指向同一个 array 对象。
组合使用构造函数模式和原型模式
四、组合使用构造函数模式和原型模式
这是目前最常用的对象创建方式,它结合了构造函数和原型模式的优点。
function Person (name,age) {
this.name=name;
this.age=age;
}
Person.prototype.showMessage = function() {
console.log("name:"+this.name+" age:"+this.age);
};
var p1=new Person("k",30);
p1.showMessage();
动态原型模式
五、动态原型模式
该模式旨在将所有信息封装在构造函数中,更符合面向对象(OO)的设计思想。
function Person (name,age) {
this.name=name;
this.age=age;
if(typeof this.showMessage!="function"){
Person.prototype.showMessage=function(){
console.log("name:"+this.name+" age:"+this.age);
}
}
}
var p1=new Person("k",30);
p1.showMessage();
寄生构造函数模式
六、寄生构造函数模式
function Person (name,age) {
var o=new Object();
o.name=name;
o.age=age;
o.sayName=function(){
console.log(this.name);
};
return o;
}
var p1=new Person("k",28);
p1.sayName();
寄生构造函数模式与工厂模式完全一致,区别在于创建对象时使用了 new 关键字,例如:var p1=new Person("k",28)。
其主要作用是在构造函数内部进行功能扩展。例如,定义一个基于 Array 数组的自定义类型 MyArray,并拥有自己的方法,如下所示。
function MyArray(){
var values=new Array();
values.push.apply(values,arguments);
//自己定义的方法
values.toPipedString=function(){
return this.join('|');
};
return values;
}
var colors=new MyArray("red","blue","green");
console.log(colors.toPipedString());
console.log(colors instanceof Array);
稳妥构造函数模式
七、稳妥构造函数模式
稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:一是不使用 this,二是不使用 new 调用构造函数。
function Person (name,age) {
var o=new Object();
var tempAge=age;
o.name=name;
o.age=age;
o.sayName=function(){
console.log(name);
}
o.sayAge=function(){
console.log(tempAge);
}
return o;
}
var p1=Person("k1",28);
p1.sayName(); // k1
p1.sayAge(); // 28
p1.name="k2";
p1.age=30;
p1.sayName(); // k1
p1.sayAge(); //28
通过上述输出可以清晰理解稳妥对象模式的含义:使用该模式创建的对象,除了初始化时传入的值(如 Person("k1",28))外,没有其他办法能改变其状态。这种对象即为稳妥对象,其实现原理依赖于 JavaScript 的闭包机制。
以上关于创建 JavaScript 对象方法的浅析内容分享完毕,希望能为大家提供参考,也希望大家多多支持本站。