JavaScript创建对象方式总结【工厂模式、构造函数模式、原型模式等】

作者:半夏

时间:2026-10-22

浏览:206

本文总结了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程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章