前端常见知识点(二)

前端常见知识点(二)

三月 06, 2019

继承

原型链

根据「红宝书」中的描述,原型链是实现继承的主要方法。其原理是利用原型让一个引用类型继承另一个引用类型的属性和方法。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Father () {
this.name = 'F'
}
Father.prototype.getFatherName = function () {
return this.name
}
function Son () {
this.sonname = "S"
}
// 创建 Father 实例,并将其赋给 Son.prototype
Son.prototype = new Father()
Son.prototype.getSonName = function () {
return this.sonname
}
var son1 = new Son()
console.log(son1.getFatherName()) // F

上述代码实现了Son继承Father,其本质是重写Son的原型对象,并以Father的实例代之,这样,原本存在于Father实例中的属性和方法,现在也存在于Son.prototype中了。

同时的,所有函数的默认原型都是Object的实例,即可以看做是

1
Father.prototype = new Object()

这样我们就有了「Son的原型对象中包含着指向Father原型的指针,Father的原型对象中又包含着指向Object原型的指针」,如此递进,形成了实例与原型的链,这就是原型链的基本概念。

但是所谓的「原型对象」又是什么呢?

原型对象

「红宝书」中说

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则来为该函数创建一个prototype属性,这个属性指向函数的原型对象。

并且在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。

例如:

1
2
3
4
function Father () {
this.name = 'F'
}
Father.prototype.constructor // function Father()

倘若我们调用构造函数创建一个新实例:

1
var father = new Father()

那么该实例的内部就会包含一个指针(内部属性),指向构造函数的原型对象。

在某些地方(Chrome,Firefox),我们可以这样访问它:

1
2
father.__proto__ // Father.prototype
father.__proto__.constructor // function Father()

并且,这个连接存在于实例与构造函数的原型对象之间,而不是实例与构造函数之间。