javaScript对象的继承

2021-08-04  本文已影响0人  番茄炒西红柿啊

目录:

1.伪继承

父类:

// 父类
function Parent(sender) {
 this.name = sender.name
}

Parent.prototype.log = function() {
 console.log('log', this.name)
}

子类:

// 子类
function Sub(sender) {
 Parent.call(this, sender)
  this.age = sender.age
}

Sub.prototype = {
  constructor: Sub,
  ...Parent.prototype
}

示例:

let sender = {name: 'diudiu', age: 18}
let s = new Sub(sender)
console.log(s)
s.log()

/// 控制台输出:
Sub { name: 'diudiu', age: 18 }
log diudiu

接着上面的代码,我们继续添加如下代码:为父类Parent再添加一个方法,并在子类s中调用

Parent.prototype.log2 = function() {
  console.log('log2', this.name)
}
s.log2()

可以看到控制台报错如下:

TypeError: s.log2 is not a function

进一步验证:

console.log(s instanceof Sub)
console.log(s instanceof Parent)

控制台输出如下:

true
false

综上所述此种方式:

优点:代码简洁。

缺点:并不是真正意义上的继承,原型链上并没有建立起继承的关系。后续如果Parent.prototype有添加新方法和属性,Sub创建的实例对象是访问不到的。

2.原型链继承

创建一个中间对象来实现继承链

父类:

// 父类
function Parent(sender) {
    this.name = sender.name
}

Parent.prototype.log = function() {
    console.log('log', this.name)
}

子类:

// 子类
function Sub(sender) {
    Parent.call(this, sender)
  this.age = sender.age
}

创建中间对象,并改写原型链关系

// 中间对象
var F = function(){}
// 将其原型对象指向父类原型对象
F.prototype = Parent.prototype
// 将子类的原型对象指向中间对象
Sub.prototype = new F()
// 修改构造方法
Sub.prototype.constructor = Sub

至此就完成了,我们可以代码验证一下:

let s = new Sub({name: 'diudiu', age: 18})
s.log()
console.log(s instanceof Sub, s instanceof Parent)

控制台输出如下:

log diudiu
true true

我们给父类扩充一个方法, 并通过子类调用:

Parent.prototype.log2 = function() {
  console.log('log2', this.name)
}
s.log2()

// 控制台输出
log2 diudiu

可以看到,后续Parent.prototype有添加新方法和属性,Sub创建的实例对象是可以访问到的。

综上所述:

优点:在原型链层面上实现了继承关系。后续 Parent.prototype有任何的属性和方法扩展,子类仍然能能够访问到。

缺单:需要创建一个中间对象来实现,要对原型链有一定的了解。

3.通过ES6特性class来实现继承关系

定义父类:

class Parent {
    constructor(sender) {
        this.name = sender.name
    }

    log() {
        console.log('log', this.name)
    }
}

定义子类:

class Sub extends Parent {
    constructor(sender) {
        super(sender)
        this.age = sender.age
    }
}

代码验证:

let s = new Sub(sender)
console.log(s)
s.log()
console.log(s instanceof Sub)
console.log(s instanceof Parent)

控制台输出:

Sub { name: 'diudiu', age: 18 }
log diudiu
true
true

可以看到子类没有定义log方法,能够访问到父类的log方法。

综上所述:

优点:代码简洁,容易理解,不需要自己来实现一个中间对象。

缺点:不是所有的主流浏览器都支持ES6的class

参考

上一篇 下一篇

猜你喜欢

热点阅读