面向对象

面向对象的语言有一个标志,那就是他们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。然而,ECMAScript中没有类的概念,所以它的对象也与基于类的语言中的对象有所不同。ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数”。

创建对象

在没有类的情况下,ECMAScript可以采用工厂模式、构造函数模式或者原型模式创建对象。

工厂模式

1
2
3
4
5
6
7
8
9
10
functiong createPerson(name,age){
var 0 = new Object();
o.name = name;
o.age = age;
o.sayName = funciont(){
alert(this.name);
};
return o;
}
var person1 = createPerson("liming", 20); //person1的类型为object

工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题,即怎么知道一个对象的类型。

构造函数模式

由于工厂模式没有解决对象识别的问题,所以可以采用构造函数模式来做。但是构造函数模式的每个成员无法得到复用,包括函数。不能在多个对象间共享函数。

1
2
3
4
5
6
7
8
function Person(name,age){
this.name = name;
this.age = age;
this.sayName = funchion(){ //每次都会创建一个function的新实例
alert(this.name);
};
}
var person1 = new Person("liming",20);

原型模式

我们创建的每个函数都有一个prototype(原型)属性,这个属性时一个指针,指向一个对象,而对这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

1
2
3
4
5
6
7
function Person(){}
Person.prototy.name = "liming";
Person.prototy.age = 20;
Person.prototy.sayName = function(){
alert(this.name);
}
var person1 = new Person(); //可以修改person1的属性

其他方法

除此以上三种基本方法外,还有结合几种方法产生的动态原型模式、寄生构造函数模式、稳妥构造函数模式等方法,分别有不同的优缺点。可根据需求选择相应的模式。

继承

许多OO语言都支持两种继承方式:接口继承和实现继承。由于函数没有签名,在ECMAScript中无法实现接口继承,所以主要依靠原形链来实现。原形链的构建是通过将一个类型的实例赋值给另一个构造函数的原型实现的,这样子类型就能够访问超类型的所有属性和方法。使用最多的继承模式是组成继承,这种模式使用原形链继承共享的属性和方法,而通过借用构造函数继承实例属性。除此外,还有原形链继承、寄生式继承、寄生组合式继承等方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//此方法实现原型链的一种基本模式
function SuperType(){
this.property = true;
}

SuperType.prototype.getSuperValue = function(){
teturn this.property;
};

function SubType(){
this.subproperty = false;
}

//继承了SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function(){
return this.subproperty;
};

var instance = new SubType();
alert(instance.getSuperValue()); //true