js中实现继承的三种方式:原型链继承、构造函数继承、组合(原型链与构造函数)继承

js中的继承

1. 继承的概念

一个类继承父类的属性和方法。 ES6之前并没有专门用于继承的关键字。 ES6之后有了Class和extends。

2. 继承的作用

一类对象是包含另一类对象的。比如说,人肯定是包含老师的。老师肯定是一个人。人的属性老师肯定有。 为了体现两者之间的关系,就需要实现继承。

3. 实现继承的方法

在ES6之前有三种

3.1 使用原型链继承

重点: 将子类的原型对象 修改为 父类的实例对象。

Son.prototype = new Father();

缺点: 缺点:

​ 1.对复杂数据类型(引用数据类型)的修改会出现误差

​ 2.继承来的属性的值都是统一的。

// 公共属性
function Person(name, age) {
    this.name = name;
    this.age = age;
}
//老师
function Teacher(jobTitle, pay) {
    this.jobTitle = jobTitle;
    this.pay = pay;
}
// 老师继承公共属性
// 实例化公共对象
var P = new Person('小黑', 20);
// 每个实例化对象都有一个原型对象
// 将公共的原型对象赋值给老师的原型对象
Teacher.prototype = P;
// 实例化老师对象
var tea = new Teacher('体育老师', 2000);


// console.log(Teacher.prototype.name);
// console.log(Teacher.prototype.age);


console.log(tea.name); //tea实例化对象里面没有name属性,会向上找原型对象,这时person的实例化对象赋给了teacher的原型对象,所以teacher里面有name属性
console.log(tea.age); //和上面的name属性一样的原理


console.log(tea.jobTitle);
console.log(tea.pay);


console.log(tea);

3.2 借用构造函数继承

重点: 在子类的构造函数中,普通方式调用父类的构造函数,需要使用call或者apply来修改 构造函数的this指向。

function Son(param1,param2){
   Father.call(this,param1,param2);

  }

缺点

1.继承来的方法只能定义在构造函数中,不能定义在父类的原型对象上

2.继承来的函数无法复用,占用内存比较大。

// 公共属性
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.eat = function() {
        console.log("干饭人干饭魂,干饭都得用大盆");
    }
}
//老师
function Teacher(name, age, pay) {

    // 如果直接调用Person(),里面的this会指向window,所以需要下面的操作
    // 强制this指向  是构造函数,this指向的是实例化对象tea
    Person.call(this, name, age);
    this.pay = pay;
}
var tea = new Teacher('离散', 12, 1000);
console.log(tea.name);
console.log(tea.age);
tea.eat();
console.log(tea);

3.3 组合继承(原型链与构造函数的组合)

组合继承:

结合了原型链继承和借用构造函数继承两者的优点;

步骤:

1.在子类的构造函数中借用父类的构造函数 father.call(this);

2.将父类的方法定义在父类的原型对象上。

3.将子类的原型对象指向 父类的实例对象

4.修正constructor属性。

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.emotion = ['喜', '怒', '哀', '乐'];
}
Person.prototype.eat = function() {
    console.log('吃', '喝', '玩', '乐');
} //将父类的方法定义在父类的原型对象上。

function Teacher(name, age, pay) {
    // 在子类的构造函数中借用父类的构造函数  
    Person.call(this, name, age); //这里的this指向的是Teacher的实例化对象
    this.pay = pay;
}
Teacher.prototype = new Person(); //将子类的原型对象指向 父类的实例对象
Teacher.prototype.constructor = Teacher; //修正constructor属性. 如果不进行修正,Teacher.prototype.constructo指向了Person

var t1 = new Teacher('小张', '10岁', '1000元');
console.log(t1.name, t1.age, t1.pay, t1.emotion);
t1.eat();

t1.emotion.push('开开心心');
console.log(t1.emotion);

var t2 = new Teacher('小刘', '10岁', '2000元');
console.log(t2.emotion);

4. 原型链继承的图解

在这里插入图片描述

5. 组合继承图解

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值