js继承(回顾)

JS基于面向对象

JS本身是基于面向对象开发的编程语言
其中,类具有封装,继承,多态性质
封装:类也是一个函数,能实现代码的封装
多态:重载、重写
重写:子类重写父类上的方法
重载:相同的方法,由于参数和返回值不同,具备不同的功能
继承:子类继承父类的方法

继承的作用

让子类的实例同时也具有父类中的私有属性和共有方法

继承的7种方案

1.原型继承

让子类的原型等于父类的实例即可

  • 优点:对象实例共享所有继承的属性和方法
  • 缺点:子类型实例的时候,不能传递参数
function Father() {
    this.a = 1
}

function Son() {}

Father.prototype.name = 'xiaomin'
Father.age = 18

Son.prototype = new Father()
var son = new Son()
console.log(son)//{a:1}
console.log(son.name)// xiaomin
console.log(son.age)// undefined

2.借用构造函数继承(call)

在子类构造函数种,把父类当作普通函数指向

  • 特点:解决了原型链实现继承的不能传参的问题和父类
  • 缺点:在父类型的原型中定义的方法,对子类型而言不可见
function Father(gender) {
    this.obj = {
        a:1,
        gender:gender
    }
}
function Son(gender) {
    Father.call(this, gender)
}
Father.prototype.name = 'xiaomin'
Father.age = 18

var son = new Son('男')
console.log(son)// { obj: { a: 1, gender: '男' } }
console.log(son.name)// undefined
console.log(son.age)// undefined

3.组合继承(经典继承)

  • 特点:解决了原型继承和传参问题
  • 缺点:无论在什么情况下,都会new两次构造函数
function Father(gender) {
    this.obj = {
        a:1,
        gender:gender
    }
}
function Son(gender) {
    Father.call(this, gender)
}
Father.prototype.name = 'xiaomin'
Father.age = 18

Son.prototype = new Father()
var son = new Son('男')
console.log(son)// { obj: { a: 1, gender: '男' } }
console.log(son.name)// xiaomin
console.log(son.age)// undefined

4.原型式继承

借用构造函数在一个函数A内部创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。
特点:本质上,执行了一次浅拷贝
缺点:属性中包含的引用值始终会在相关对象间共享,子类实例不能向父类传参

function createObj(obj) {
    function F() {}
    F.prototype = obj
    return new F()
}  // 同 Object.create(obj)

let obj = {
    a: 1,
    arr:[]
}
obj.age = 18

var son1 = createObj(obj)
son1.arr.push('男')
console.log(son1)//{}
console.log(son1.a)// 1
console.log(son1.age)// 18
var son2 = createObj(obj)
console.log(son2.arr)//[ '男' ]

5.原型式继承

  • 优点:高效率只调用一次父构造函数
  • 缺点:代码复杂
function inFatherit(Target, Origin) {
    function F(){}
    F.prototype = Origin.prototype
    Target.prototype = new F()
    Target.prototype.constructor = Target // 防止子类的构造器指向父类
    Target.prototype.uber = Origin.prototype
}
function Father(gender) {
    this.obj = {
        a:1,
        gender:gender
    }
}
function Son(gender) {
    Father.call(this, gender);
}
Father.prototype.name = 'xiaomin'
Father.age = 18

inFatherit(Son,Father)
var son = new Son('男')
console.log(son)// { obj: { a: 1, gender: '男' } }
console.log(son.name)// xiaomin
console.log(son.age)// undefined

6.ES6,class继承

  • 特点:父类实例对象的属性和方法,加到this上面(所以必须先调用super方法)
  • extends(继承)后一定要在如果写了 constructor 要在第一行加上 super()
class Father {
    constructor(gender) {
        this.obj = {
            a: 1,
            gender: gender
        }
    }
     a = 1
    static b = 2
}

class Son extends Father {
    constructor(gender) {
        super(gender);
    }
}

Father.prototype.name = 'xiaomin'
Father.age = 18

var son = new Son('男')
console.log(son)//Son  { a: 1, obj: { a: 1, gender: '男' } }
console.log(son.name)// xiaomin
console.log(son.age)// undefined

7.superClass.prototype.constructor.call(this)

原理ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到 this 上面(Parent.call(this))

// 1.父构造函数
function Father(uname, age) {
  // this指向父构造函数的对象实例
  this.uname = uname;
  this.age = age;
}
Father.prototype.money = () => {
  console.log(100000);
};
// 2.子构造函数
function Son(uname, age, score) {
  Father.prototype.constructor.call(this, uname, age);
  // console.log(Father())
  // this指向子构造函数的对象实例
  // Father.call(this, uname, age); //调用父构造
  console.log(Father.prototype.constructor);
  this.score = score;
}
var son = new Son("刘德华", 18, 100);
console.log(son); //{uname: '刘德华', age: 18, score: 100}

参考

链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳晓黑胡椒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值