面向对象程序设计

假如没有对象,那么你就自己new 一个对象出来呗

1.工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function createPerson (name, age, job) {
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function () {
console.log(this.name)
}
o._this = this
return o
}

var p = createPerson('chris', 18, 'softwate engineer')
p.sayName()
console.log(p._this === this) // 这里的Person 的 this 指向windows全局

2.构造函数模式

ECMAScript可以使用构造函数创建特定的类型对象 使用new操作符实例化新对象 1)创建一个新对象 2)将构造函数的作用域复制给新对象(this指向这个对象) 3)执行构造函数中的代码(为这个新对象添加属性) 4)返回新对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function Person (name, age, job) {
this.name = name
this.age = age
this.jpb = job
this._this = this
this.sayName = function () {
console.log(this.name)
}
}
// 作为构造函数调用
var p1 = new Person('chris', 18, 'software engineer')// 这里的this指向Person构造函数
p1.sayName()
console.log(p1._this === this)
/*****************************/
// 作为普通函数调用
Person('p2name', 18, 'software engineer') // Person 挂载在全局上
window.sayName()

/*****************************/
// 在另外一个作用域中调用
var o = new Object();
Person.call(o, 'kisten', 25, 'Nurce')
o.sayName()

缺点

每个方法都要在每个实例中重新创造一遍。 即:p1.sayName() 与 p2.sayName() 不相同

3.原型模式

每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象。这个对象的用途就是包含所有实例共享的属性和方法。

1
2
3
4
5
6
7
8
9
10
11
function Person(){}
Person.prototype.name = 'chris'
Person.prototype.age = 18
Person.prototype.sayName = function () {
console.log(this.name)
}
var p1 = new Person()
p1.sayName()
var p2 = new Person()
p2.sayName()
console.log(p1.sayName() === p2.sayName())

使用字面量 构建原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person(){}
Person.prototype = {
constructor: Person, // 使用过prototype等于重写了整个原型对象,所以需要在构造方法中重新指向Person()
name: 'chris',
age: 18,
sayName: function () {
console.log(this.name)
}
}
var p1 = new Person()
p1.sayName()
var p2 = new Person()
p2.sayName()
console.log(p1.sayName() === p2.sayName())

缺点

原型中很多属性都是共享等,对于函数非常方便,对于属性就不是很方便。而且修改其中一个属性会影响另外实例的属性(因为属性和方法共享)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Person(){}
Person.prototype = {
constructor: Person, // 使用过prototype等于重写了整个原型对象,所以需要在构造方法中重新指向Person()
name: 'chris',
age: 18,
arr: [1,2],
sayName: function () {
console.log(this.name)
}
}

var p1 = new Person()
var p2 = new Person()
console.log(p1.arr, p2.arr) // [1,2], [1,2]
p1.arr.push(12)
console.log(p1.arr, p2.arr) // [1, 2, 12] [1, 2, 12]

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person (name, age){
this.name = name
this.age = age
}

Person.prototype = {
constructor: Person,
sayName () {
console.log(this.name)
}
}

var p1 = new Person('p1', 18)
var p2 = new Person('p2', 18)
console.log(p1.name, p2.name)