理解js继承


前言

就学习的js继承作一学习记录,备查.


一、继承

1.原型继承

  • 子对象自动拥有父对象的属性和方法, 继承可以提高代码的复用性;
  • 原型对象(每一个构造函数都有一个原型对象)的值等于另一个类型的实例

二、几种继承方式

1.原型链继承

让子对象的原型指向父对象的实例,父对象的原型指向爷爷对象的实例,依次类推,就形成了原型链

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  function Student(id,score){
    this.id = id;
    this.score = score;
  }
  Student.prototype = new Person("laowang",18);
  Student.prototype.study = function(){
    console.log(this.name + " study");
  }
  let s = new Student(1,100);
  console.log(s.name,s.age,s.id,s.score);//laowang 18 1 100
  s.eat();//laowang eat
  s.study();//laowang study

**重点:让新实例的原型等于父类的实例

注意事项:

  • 1.由父类派生给子类的属性,无法初始化;
  • 2.子类对象在添加新的方式时,一定要保证,先实现继承,再添加原型方法

2.构造函数继承

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  function Student(id,score,name,age){
    Person.call(this,name,age);//这一步相当于复制Person里this.name=name;this.age=age;
    this.id = id;
    this.score = score;
  }
  let s = new Student(1,100,"laowang",18);
  console.log(s.id,s.score,s.name,s.age);//1 100 laowang 18
  s.eat();//报错

**重点:用.call()和.apply()将父类构造函数引入子类函数

注意事项:

  • 1.只能继承父类构造函数的属性,不能继承方法
  • 2.无法实现构造函数的复用

3.组合继承

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  function Student(id,score,name,age){
    Person.apply(this,[name,age]);
    this.id = id;
    this.score = score;
  }
  Student.prototype = new Person();
  Student.prototype.study = function(){
    console.log(this.name + " study");
  }
  let s = new Student(1,100,"laowang",18);
  console.log(s.id,s.score,s.name,s.age);//1 100 laowang 18
  s.eat();//laowang eat
  s.study();//laowang study

**重点:结合构造函数继承和原型链继承

4.原型式继承

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  function fun(person){//封装一个函数容器
    function F(){};
    F.prototype = person;//继承传入的实例对象原型
    return new F();//返回函数对象
  }
  let s1 = new Person("laowang",18);
  let s = fun(s1);
  console.log(s.name,s.age);//laowang 18
  s.eat();//laowang eat

封装fun()和Object.create()一样.(ES5中新增加方法)

Object.create()方法会使用指定的原型对象及其属性去创建一个新的对象.从本质上讲,相当于对传入的对象进行了一次浅拷贝.

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  let s1 = new Person("laowang",18);
  // let s = fun(s1);
  let s = Object.create(s1);
  console.log(s.name,s.age);//laowang 18
  s.eat();//laowang eat

**重点:类似于复制一个对象,用函数来包装。

注意事项:

  • 1.所有的实例都会继承原型上的属性
  • 2.无法实现复用。

5.寄生式继承

寄生式继承是于原型式继承紧密相关的一种思路,既创建一个仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  let s1 = new Person("laowang",18);
  function Student(s1){
    let stu = Object.create(s1);
    stu.id = 1;//可以为其增加属性及方法
    stu.score = 100;
    stu.study = function(){
      console.log(stu.name + " study");
    }
    return stu;
  }
  let s = Student(s1);
  console.log(s.name,s.age,s.id,s.score);//laowang 18 1 100
  s.eat();//laowang eat
  s.study();//laowang study

**重点:重点:就是给原型式继承外面套了个壳子

注意事项:

  • 没用到原型,无法复用

6.寄生组合继承

寄生式与组合式相结合的继承方式,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

组合式继承最大的弊端是会两次调用构造函数,浪费内存.与寄生继承结合解决这一问题.

背后的基本思路:使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

  function Person(name,age){
    this.name = name;
    this.age = age;
  }
  Person.prototype.eat = function(){
    console.log(this.name + " eat");
  }
  function Student(id,score){
    this.id = id;
    this.score = score;
  }
  function inheritPrototype(subType,superType){
    // let prototype = Object.create(superType.prototype);//创建Person类的原型对象副本
    let prototype = Object.create(superType.prototype,{name:{value:"laowang"},age:{value:18}});
    prototype.constructor = subType;//修改副本的属性值 ??
    subType.prototype = prototype;//把生成好的对象赋值给子类原型 ??
  }
  // Student.prototype = new Person("laowang",18);
  inheritPrototype(Student,Person);//这句与上句等价
  Student.prototype.study = function(){
    console.log(this.name + " study");
  }
  let s = new Student(1,100);
  // s.name = "laowang";
  // s.age = 18;
  console.log(s.name,s.age,s.id,s.score);//laowang 18 1 100
  s.eat();//laowang eat
  s.study();//laowang study

三、ES6继承

  class Person{
    constructor(name,age){
      this.name = name;
      this.age = age;
    }
    eat(){
      console.log(this.name + " eat");
    }
  }
  class Student extends Person{
    constructor(id,name,age){
      super(name,age);//super一定要写在前面!!
      this.id = id;
    }
    study(){
      console.log(this.name + " study");
    }
  }
  let s = new Student(1,"nana",18);
  console.log(s.id,s.name,s.age);//1 nana 18
  s.eat();//nana eat
  s.study();//nana study

参考

1.js继承的6种方式
2.JavaScript-------寄生组合式继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值