前言
起初接触JS时常见的简单地创建单个对象的方式有下面三种:
- 字面量,即var obj = {}
- new Object()
- Object.create()
以上三种方式在需要创建很多对象时会产生大量重复代码。显然需要更高效的方式,下面将介绍7种创建对象的方式
1. 工厂模式
1.1介绍
工厂模式正是源自设计模式中的工厂模式,其基本思想:
- 既然创建对象数量多时产生了大量重复代码
- 那就建一座工厂,通过工厂来创建加工
- 再返回创建好的对象
function createPerson(name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.getName = function() {
console.log(this.name)
}
return obj
}
var person1 = createPerson("AAA", 23)
person1.getName() //AAA
var person2 = createPerson("BBB", 30)
person2.getName() //BBB
1.2 优劣分析
- 解决了复用性的问题
- 但无法判断对象的类型(只知道是Objcet类型)
2. 构造函数模式
2.1 介绍
构造函数可创建特定类型的对象,类似Object和Array(实际上Object和Array本身就是构造函数)
function Person(name, age) {
this.name = name
this.age = age
this.getName = function() {
console.log(this.name)
}
}
var person1 = new Person("AAA", 23)
person1.getName() //AAA
var person2 = new Person("BBB", 30)
person2.getName() //BBB
通过上面代码我们可以看到构造函数模式:
- 没有通过new Object()显示创建对象
- 属性和方法赋值给了this
- 无需return
2.2 构造函数也是函数
构造函数其实也是个函数,只是可以通过new调用来创建对象,当然也可作为普通函数使用
//作为普通函数使用
Person("CCC", 24)
Person.getName() //CCC
//在一个对象内调用
var obj = {}
Person.call(obj, "DDD", 25)
obj.getName() //DDD
2.3 优劣分析
- 构造函数模式可以创建具体类型的对象
console.log(person1 instanceof Object) //true
console.log(person1 instanceof Person) //true
- 然而,构造函数中的方法是通用的,但每个实例都创建了一份属于自己的副本,造成内存浪费
console.log(person1.getName === person2.getName) //false
3. 原型模式
3.1 介绍
原型模式即通过原型对象来实现属性和方法的共享,实例对象不会创建各自的副本
要理解原型模式,建议先理解透彻JS原型的概念——推荐阅读一张图彻底KO原型链(prototype,__proto__)
function Person() {
}
Person.prototype.name = "AAA"
Person.prototype.age = 23
Person.prototype.getName = function() {
console.log(this.name)
}
var person1 = new Person()
person1.getName() //AAA
var person2 = new Person()
person2.name = "BBB"
person2.getName() //BBB
console.log(person1.getName === person2.getName) //true
然而原型对象也存在缺陷——对于引用类型的属性,各实例对象间指向同一个地址,某个对象修改了属性,所有对象都会受到影响
function Person() {
}
Person.prototype.arr = [1,2,3]
Person.prototype.getArr = function() {
console.log(this.arr)
}
var person1 = new Person()
person1.arr.push(4)
person1.getArr() //1,2,3,4
var person2 = new Person()
person2.getArr() //1,2,3,4
person1.arr.push(5)
person1.getArr() //1,2,3,4,5
person2.getArr() //1,2,3,4,5
3.2 优劣分析
- 原型模式解决了属性和方法的共享问题
- 但对于引用类型的属性,各实例对象会相互影响
4. 组合模式
4.1介绍
组合模式即组合构造函数模式和原型模式,取二者之长,构造函数模式用于定义实例的属性,原型模式用于定义方法和共享的属性
function Person(name, age) {
this.name = name
this.age = age
this.arr = [1,2,3]
}
Person.prototype = {
getName: function() {
console.log(this.name)
}
}
var person1 = new Person("AAA", 23)
person1.arr.push(4)
console.log(person1.arr) //1,2,3,4
person1.getName() //AAA
var person2 = new Person("BBB", 30)
console.log(person2.arr) //1,2,3
person2.getName() //BBB
4.2 优劣分析
- 组合模式是使用最广泛的一种模式,尤其在需要定义引用类型时
5. 动态原型模式
5.1 介绍
刚说组合模式是认可度最高的一种模式,然而也有些美中不足——每创建一个实例对象,原型方法都被重复定义一次
动态原型模式正是解决这个问题,使用if语句,使得原型方法只初始化一次
function Person(name, age) {
this.name = name
this.age = age
//这里只需要使用任何一个方式或属性,不一定是getName,getAge也可以
//只要保证if里面的代码只执行一次就行
if(typeof this.getName !== 'function') {
Person.prototype.getName = function() {
console.log(this.name)
}
Person.prototype.getAge = function() {
console.log(this.age)
}
}
}
var person = new Person("AAA", 23)
person.getName() //AAA
5.2 优劣分析
- 动态原型模式在组合模式的基础上做了优化,可谓更加完美
6. 寄生构造函数模式
6.1 介绍
长得和工厂模式一样,但调用方式和构造函数模式一样的模式,通过new调用构造函数,本该返回一个实例对象,但return语句重写了构造函数的返回值
function Person(name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.getName = function() {
console.log(this.name)
}
return obj
}
var person = new Person("AAA", 23)
person.getName() //AAA
6.2 优劣分析
-
这种方式和工厂模式没什么不同,要说不同的就是通过new来调用,仍然存在工厂模式的无法判别对象类型的问题
-
个人认为这是一种多余的方式,复杂而不好理解,也没有什么应用场景
7. 稳妥构造函数模式
7.1 介绍
先介绍一个概念——稳妥对象:
- 没有公共属性
- 不使用this
- 不使用new调用
稳妥构造函数模式和工厂模式类似,但遵循稳妥对象的原则
function Person(name, age) {
var obj = new Object()
//getName是唯一读取name的方式
obj.getName = function() {
console.log(name)
}
return obj
}
var person = Person("AAA", 23)
person.name = "BBB" //无效
person.getName() //AAA
7.2 优劣分析
- 稳妥构造函数模式的特点就是安全性,适用于某些需要安全执行的环境
- 类似工厂模式,无法判别对象类型
8. 总结
-
工厂模式:解决了大量重复代码的问题,但无法判别对象类型
-
构造函数模式:实例对象又具体的类型,但每个实例对象都有方法的副本,造成内存浪费
-
原型模式:可共享方法和属性,但存在引用类型相互影响的问题
-
组合模式:取构造函数模式和原型模式之长**(最常用)**
-
动态原型模式:优化了组合模式
-
寄生构造函数模式:类似工厂模式,只是通过new调用
-
稳妥构造函数模式:类似工厂模式,只是提升了安全性
后记
希望本文对你有帮助,更多文章将持续更新……
感谢你的点赞和鼓励
与本文相关的文章有: