原型与继承

原型与原型链

把当前对象作为实例来看待,那么他的__proto__是他的原型,而他的原型本身则是原型的原型的实例,而实例与原型的关系就构成了原型链

原型的概念

  1. 普通object类型下,原型存储在__proto__中,它有两个属性,constructor和__proto__
  2. 在函数类型中,有函数属性protoype,prototype有一个默认的constructor属性,用于记录实例是由哪个构造函数创建
  3. 原型对象的constructor指向构造函数本身
  4. 实例的__proto__与原型对象相等,即指向同一个内存地址

原型的优势

  1. 实例对属性的方法进行覆盖和重写不会影响原型
  2. 原型链的关系可以减少内存消耗

原型继承

原型链继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function VehicleInc(name) {
this.name = name
}

VehicleInc.prototype.getName = function() {
return this.name
}

function Benz() {
this.model = []
}

Benz.prototype = new VehicleInc('Benz')
Benz.prototype.addModel = function (model) {
this.model.push(model)
}

const benz = new Benz();

借用构造函数实现继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function VehicleInc(name) {
this.name = name
this.getName = function() {
return this.name
}
}

function Benz() {
VehicleInc.call(this, 'Benz')
this.model = []
this.addModel = function () {
this.model.push()
}
}

Benz.prototype = new VehicleInc()

const benz = new Benz();

组合式继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function VehicleInc(name) {
this.name = name
}

VehicleInc.prototype.getName = function() {
return this.name
}

function Benz() {
VehicleInc.call(this, 'Benz')
this.model = []
}

Benz.prototype = new VehicleInc()
Benz.prototype.constructor = Benze
Benz.prototype.addModel = function(model) {
this.model.push(model)
}

const benz = new Benz();

寄生组合式继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function VehicleInc(name) {
this.name = name
}

VehicleInc.prototype.getName = function() {
return this.name
}

function Benz() {
VehicleInc.call(this, 'Benz')
this.model = []
}

Benz.prototype = Object.create(VehicleInc.prototype)
Benz.prototype.constructor = Benz
Benz.prototype.addModel = function(model) {
this.model.push(model)
}

const benz = new Benz();

类继承
使用extends关键字

super

  1. 实现继承必须使用super,因为子类没有this, 如果不调用子类就得不到this对象
  2. super作为函数调用时是作为父类的构造函数
  3. super作为对象时,调用实例方法时为父类的原型对象,调用静态方法时为,super作为父类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class VehicleInc {
constructor(name) {
this.name = name
}

getName() {
return this.name
}
}

class Benz extends VehicleInc {
constructor() {
super('Benz')
this.model = []
}
addModel(model) {
this.model.push(model)
}
getAllModel() {
return `the ${super.getName()} has ${this.model.join('、')} models`
}
}