工厂模式

创建一个函数,该函数创建一个对象,包含所有需要的信息,最终返回该函数

举例来说,创建一个 Person 类:

1
2
3
4
5
6
7
8
9
10
function Person(name, age, job) {
var obj = new Object()
obj.name = name
obj.age = age
obj.job = job
obj.sayName = function () {
console.log(this.name)
}
return obj
}

工厂模式虽然可以创建相似的类的实例,但是事实上每个属性和方法在不同的实例上重新创建了一遍,并且无法识别成一个特定的类型

1
2
3
4
5
var p1 = Person('Tom', 20, 'driver')
var p2 = Person('Mike', 34, 'doctor')

console.log(p1.sayName === p2.sayName) // => false
console.log(p1 instanceof Person) // => false

构造函数模式

通过创建构造函数定义类的属性和方法

1
2
3
4
5
6
7
8
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function () {
console.log(this.name)
}
}

使用构造函数模式没有显示的创建对象,而是直接将属性和方法赋值给this,同时没有return语句

通过构造函数创建新实例,必须通过new调用,调用过程要经过以下几步:

  1. 创建一个新对象

  2. 将构造函数的作用域赋给新对象,this指向新对象

  3. 执行构造函数中的代码

  4. 返回新对象

使用这种方法创建的实例会被标识为特殊的类型,但是工厂模式的另一个问题依然没被解决,即公用的方法会被重复创建

1
2
3
4
5
var p1 = new Person('Tom', 20, 'driver')
var p2 = new Person('Mike', 34, 'doctor')

console.log(p1.sayName === p2.sayName) // => false
console.log(p1 instanceof Person) // => true

原型模式

每个函数都有prototype属性,用来包含特定类型的所有实例共享的的属性和方法

1
2
3
4
5
6
7
8
function Person() {}

Person.prototype.name = 'Tom'
Person.prototype.age = 20
Person.prototype.job = 'doctor'
Person.prototype.sayName = function () {
console.log(this.name)
}

使用这种方法所有实例都将取得相同的属性值

1
2
3
4
5
6
var p1 = new Person()
var p2 = new Person()

p1.sayName() // => 'Tom'
p2.sayName() // => 'Tom'
console.log(p1 instanceof Person) // true

组合使用构造函数模式和原型模式

这是最常见的方式,构造函数模式用于定义实例属性,原型模式用于定义方法和共有的属性

1
2
3
4
5
6
7
8
9
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
}

Person.prototype.sayName = function () {
console.log(this.name)
}

组合使用两种方法创建的实例可以被标识为类的实例,并且不用重复创建共有的方法和属性

1
2
3
4
5
var p1 = new Person('Tom', 20, 'driver')
var p2 = new Person('Mike', 34, 'doctor')

console.log(p1.sayName === p2.sayName) // => true
console.log(p1 instanceof Person) // => true