实现js继承的方法

js继承的几种方式

​ 继承是面向对象技术当中的一个概念。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

​ 继承在js中占有非常重要的地位,那么在js中有很多中继承的方式,不过每一种继承方式都有优缺点。下面就列举几种继承的方式。

1.构造函数继承

实现方式 :使用call等方法 使一个对象的this指向另一个对象 从而让其拥有这个对象的属性和方法在将来创建的新对象里执行

super.call(this)//其实这个this指的就是当前的对象,
//因为用new 构造出来的实例,会把this指向该实例本身,所以

function Father(name) {
        this.name=name
    }

    function Child(age) {
        Father.call(this,'小黄')
        this.age=age;
    }
    let child=new Child(19)
    console.log(child);//Child {name: "小黄", age: 19};

优点:
创建子类实例时,可以向父类传递参数
可以实现多继承(call多个父类对象)

缺点 : 无法继承父类原型上面的方法 对于子类不需要的方法 每次创建都会拥有 浪费内存空间

2.原型链继承

**核心:**父类的实例作为子类的原型

function Animal() {
       this.color=['red','blue']
   }
   Animal.prototype.eat=function(){
       console.log('eat')
   };

   function Dog(){

   }

   Dog.prototype=new Animal();

   let dog=new Dog();
   console.log(dog.color);
   dog.eat(); //eat

优点:

简单易于实现,父类的新增的实例与属性子类都能访问

缺点:

可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面

无法实现多继承

创建子类实例时,不能向父类构造函数中传参数

3.原型拷贝继承(混入式继承)

实现方式 :使用for-in遍历父类原型里面的所有属性,依次加入子类的原型中

function Parent(name, age){
            this.name = name;
            this.age = age;
            this.work = function(){
                console.log("我要赚钱养家");
            }
        }

        Parent.prototype.test = function(){
            console.log(111);
        }
        Parent.prototype.type = "人类";

        function Child(name, age){
            this.name = name;
            this.age = age;
        }

        // 原型对象拷贝
        for(var key in Parent.prototype){
            Child.prototype[key] = Parent.prototype[key];
            console.log(Parent.prototype[key]);//function(){console.log(111);}  
        }  

        var c1 = new Child("zhangsan", 12)
        c1.test();
        console.log(c1.type);  //人类

缺点 :原型中子类不需要的方法或者属性也继承过来了 占用内存空间
优点 : 支持多继承

4.实例继承(原型式继承)

function Wonman(name){
  let instance = new People();
  instance.name = name || 'wangxiaoxia';
  return instance;
}
let wonmanObj = new Wonman();

优点:

不限制调用方式

简单,易实现

缺点:不能多次继承

5.组合式继承

也叫伪经典继承。指的是将原型链和借用构造函数的技术组合到一起,从而发挥二者之长。
调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用

function Father(name) {
        this.name=name
    }
     Father.prototype.sayName=function () {
         console.log(this.name);
     }
    function Child(name,age) {
        Father.call(this,name)
        this.age=age;
    }
    Child.prototype=new Father();
    Child.prototype.sayAge=function(){
        console.log(this.age);
    }
    let child1=new Child('xiao',13);
        child1.sayName();
        child1.sayAge()

    let child2=new Child('big',14);
        child2.sayName()
         child2.sayAge();

缺点:

由于调用了两次父类,所以产生了两份实例

优点:
既通过在原型上定义方法实现了函数复用,又能保证每一个实例都有它自己的数组。

6.寄生组合继承

是JavaScript最常用的继承模式。
通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型

 function createAnother(original) {
  var clone = object(original); // 通过调用 object() 函数创建一个新对象
  clone.sayHi = function() {
    // 以某种方式来增强对象
    console.log("hi");
  };
  return clone; // 返回这个对象
}
// 函数的主要作用是为构造函数新增属性和方法,以增强函数
var person = {
  name: "Nicholas",
  friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"```

7…ES5 和 ES6继承

ES6继承

实质上是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this。

ES6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其进行加工。如果不调用super方法,子类得不到this对象



/*
class是个关键词,语言糖,这样能更清晰的读懂所创建的对象,
通过属性constructor来接收控制方法传入的参数,如果不写这个属性,默认是没有参数的
es5中constructor为隐式属性

class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
class中定义的所有方法是不可枚举的
class中只能定义方法,不能定义对象,变量等
*/

class People{
  constructor(name='wang',age='27'){
    this.name = name;
    this.age = age;
  }
  eat(){
    console.log(`${this.name} ${this.age} eat food`)
  }
}
//继承父类
class Woman extends People{ 
   constructor(name = 'ren',age = '27'){ 
     //继承父类属性
     super(name, age); 
   } 
    eat(){ 
     //继承父类方法
      super.eat() 
    } 
} 
let wonmanObj=new Woman('xiaoxiami'); 
wonmanObj.eat();

ES5继承

ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上

ES5 通过新增 Object.create()方法规范化了原型式继承,此方法可以接受两个参数,第一个参数最为新对象原型的对象 和一个为新对象定义额外属性的对象

var person = {
  name: "kebi",
  friends: ["kuli", "hadeng"]
};
var onePerson = Object.create(person, {
  name: "heyushuo"
});
onePerson.friends.push("heyushuo");
var twoPerson = Object.create(person, {
  name: "yaoming"
});
twoPerson.friends.push("yaoming");
//这里打印
console.log(twoPerson); //['kuli','hadeng','heyushuo','yaoming']
// 主:在没有必要创建构造函数,而是指向让一个对象与另外一个对象保持类似的情况下,原型式继承完全可以胜任

ES5继承和ES6继承的区别

1.ES5先创建子类,在实例化父类并添加到子类this中
2.ES6先创建父类,在实例化子集中通过调用super方法访问父级后,在通过修改this实现继承

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值