第9章 类和模块

类和构造函数

构造函数的 prototype 属性被用作新对象的原型。这就意味着通过同一个构造函数创建的所有对象都继承自同一个对象。

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

Person.prototype = {
speak: function() {
console.log('hello world');
}
};

var xiaoming = new Person('小明', 18);

xiaoming.speak();

构造函数和类的标识

原型对象是类的唯一标识:当且仅当两个对象继承自同一个原型对象时,它们才是属于同一个类的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var base = {
id: 0
};

function Cat() {
this.name = 'cat';
}
Cat.prototype = base;

function Dog() {
this.age = 18;
}
Dog.prototype = base;

var c = new Cat();
var d = new Dog;
console.log(c instanceof Dog);

结果为 true

constructor属性

任何JavaScript函数都可以作为构造函数,并且调用构造函数需要用到一个prototype属性。因此每个函数都自动拥有一个prototype属性。这个属性的值是一个对象,这个对象包含唯一一个不可枚举属性constructor。constructor的值是一个函数对象。

1
2
3
var F = function(){};	// 这是一个函数对象
var c = F.prototype.constructor;
c === F

结果为 true

上例中由于Person将原型指向一个新对象代替了默认的Person.prototype对象,这个新对象不含有contructor属性,所以Person的实例也不含有constructor属性。可以通过补救来修正它:

1
2
3
4
5
6
Person.prototype = {
constructor: Person,
speak: function() {
console.log('hello world');
}
};

显示的设置构造函数反向引用,或者:

1
2
3
Person.prototype.speak = function(){
console.log('hello world');
};

为原型对象添加方法。
在实践中,推荐使用后者。

Java式的类继承

P207