通常我们创建一个自定义对象可以使用以下两种方法

  1. 使用对象字面量

    1
    var obj = {name: 'nany', sex: 'female', run: function(){ /* do something */ }}
  2. 使用构造函数

    1
    2
    3
    var obj = new Object()
    obj.name = 'nany'
    obj.sex = 'female'

以第一种方法为例(为啥不选第二种?就不选第二种!),当我们需要创建100个有run方法的对象时,那么我们需要这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var person1 = {
name: 'nany',
sex: 'female',
run: function(){
// do something
}
}
var person2 = {
name: 'lily',
sex: 'female',
run: function(){
// do something
}
}
......
var person100 = {
name: 'jack',
sex: 'male',
run: function(){
// do something
}
}

是不是感觉没有爱了?我只有一个run方法想和你一样竟然要写这么多代码,不能忍,为了解决这个写很多遍重复代码的问题,机智的程序员提出了一种设计模式:工厂模式

1
2
3
4
5
6
7
8
9
10
11
function createPerson(name, sex){
var person = new Object()
person.name = name
person.sex = sex
person.run = function(){
// do something
}
return person
}
var person1 = createPerson('nany', 'female')
var person2 = createPerson('jack', 'male')

现在你总不会说代码多又重复了吧?每个有不同的属性值又都有run方法,JS之父看我们又是写var 又是return的,为了让我们再少些几行代码,给我们提供了new这个关键字,同时我们使用了this

1
2
3
4
5
6
7
8
9
function Person(name, sex){
this.name = name
this.sex = sex
this.run = function(){
// do something
}
}
var person1 = new Person('nany', 'female')
var person2 = new Person('jack', 'male')

在这里new帮我们做了如下的事情:

  1. 不用显示的创建对象,因为 new 会帮你做(使用「this」就可以访问到临时对象);
  2. 直接将属性和方法赋给了this对象
  3. 不用 return 对象,因为 new 会帮你做;

这个模式被称为构造函数模式,按照惯例,构造函数始终都应该以一个大写字母开头,并且使用new操作符来创建构造函数的实例。

那么问题又来了,我们不需要每次创建对象的时候再重写run方法,因为我们发现
person1.run === person2.run // false,我们想要person1的run和person2的run是一样的,这样就没必要每次创建person的时候重复创建run方法了,而用原型链可以解决这个问题

1
2
3
4
5
Person.prototype = {
run: function(){
// do something
}
}

注意:如果重新给Person.prototype赋值,那么你的 constructor 属性就没了,所以需要这么写

1
2
3
4
5
6
Person.prototype = {
constructor: Person
run: function(){
// do something
}
}

或者这么写

1
2
3
Person.prototype.run = function(){
// do something
}

至此,整个代码是这样的

1
2
3
4
5
6
7
8
9
function Person(name, sex){
this.name = name
this.sex = sex
}
Person.prototype.run = function(){
// do something
}
var person1 = new Person('nany', 'female')
var person2 = new Person('jack', 'male')

这个模式被称为原型模式,在这里new 总共帮我们做了如下的事情:

  1. 不用显示的创建对象,因为 new 会帮你做(使用「this」就可以访问到临时对象);
  2. 直接将属性和方法赋给了this对象;
  3. 不用 return 对象,因为 new 会帮你做;
  4. 不用绑定原型,new指定原型的名字为 prototype;

参考