js的几种继承方式

449 阅读3分钟

继承在js中占有非常重要的地位,在js当中有很多继承方式。但是优缺点有所不同。

Es5继承

1.实现继承首先需要一个父类,在js中实际上没有类的概念但在,es6中class虽然很像类,但实际上只是es5上语法糖。

  this.name  = name || Annie
  //实例方法
  this.sleep=function(){
    console.log(this.name + 在睡觉')
  }
}
//原型方法
Peoples.prototype.eats = function(food){
  console.log(this.name + '在吃:' + food);
}

2.原型链继承

function Child() {} //子类
 Child.prototype.sleep=function(){
     console.log(this.name+"is sleeping")
 }
Child.prototype = new Parent("yzh")
//为了不破坏原型链,将Male的constructor指向本身
Child.prototype.constructor=Child
Child.prototype.sleep=function(){
    console.log(this.name+" is sleeping")
}

Parent.prototype.eat=function(){
    console.log(this.name+" is eating")
}
var child=new Child()
console.log(Child)

2.优缺点

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

缺点:1.可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new父类构造函数的后面
无法实现多继承

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

构造函数继承

步骤

1.在子类的构造函数中执行父类的构造函数,并为其绑定子类的this。

2.通过call()函数,改变this的指向,让父类的构造函数把成员属性和方法都挂到子类的this上去。

function Father(name,age){// Father构造函数是父类
    this.name = name;
    this.age = age;
    this.say = function(){
        console.log('天天努力');
    }
}
//构造函数继承的方式,子类继承不到父类原型上的属性和方法
Father.prototype.setNames=function(){console.log('原型上的方法')}
function Childs(name,age,sex){// Childs构造函数是子类
    // 执行父类构造方法并绑定子类的this, 使得父类中的属性能够赋到子类的this上
    Father.call(this,name,age);// 子类继承父类的属性
    this.sex = sex;// 子类可以拥有自己的特有属性
}
var f1 = new Father('迪迦',100);
var c1 = new Childs('孙悟空',20,70);

2.优缺点

优点:1避免共享一个原型实例,向父类构造方法传参。

缺点:1.继承不到父类原型上的方法。

组合继承

步骤

1.是构造继承和原型链继承的组合体。

function Father(name,age){
    this.name = name;
    this.age = age;
}
Father.prototype.greeting = function(){
    console.log('nice meeting you');
}
function Childs(name,age,sex){
    Father.call(this,name,age);
    this.sex = sex;
}
Childs.prototype = new Father();
Childs.prototype.student = function(){
    console.log('Goodbye');
}
var c1 = new Childs('迪迦',30,80);
console.log(Childs.prototype);
console.log(c1.__proto__);
console.log(c1);
c1.greeting();
c1.student();

2.优缺点

优点:1每次创建子类实例都执行了两次构造函数(Father.call()和new Father())。

缺点:1.组合继承保留了原型链继承和构造继承的优点,还规避了他俩的缺点。

寄生式继承

步骤

1.对象或某些信息创建一个对象,然后增强对象,最后返回对象。

function parasitism(o){ //对象
    function Father(){};
    Father.prototype = o;
    return new Father; 
}

function Childs(o){
    var  consp = parasitism(o);
    consp.say = function(){
        console.log('hello');
    }
    return consp;
}
var Person = {
    name:'迪迦',
    age:101
}
var c1 = Childs(Person);
console.log(c1);
console.log(c1.name);
console.log(c1.age);
c1.say();

2.优缺点

优点:1解决了组合继承中每次创建子类实例都执行了两次构造函数

缺点:1.原型继承存在的缺点他都存在

寄生式组合继承

  1. 使用寄生式继承来继承超类型的原型。
  2. 将结果指定给子类型的原型。
function Father(name){
    this.name = name;
}
Father.prototype.getName=function(){
    console.log(this.name);
}
function transcript(son,father){
    function F(){};
    F.prototype = father.prototype;
    var prototype = new F;
    prototype.constructor = son;
    son.prototype = prototype;
}
function Childs(name,age){
    Father.call(this,name);
    this.age = age;
}
//将子类Childs的原型指向父类原型的一个副本
//注意:要执行该动作后才能在Childs的prototype上定义方法,否则没用
transcript(Childs,Father);
Childs.prototype.getAge=function(){
    console.log(this.age);
}
var c1 =new Childs('迪迦',108);
console.log(c1);
c1.getName();
c1.getAge();

2.优缺点

优点:1集寄生式继承和组合式继承的优点与一身,实现基本类型继承的最有效方法。

缺点:1.调用了一次父类(father),并且避免了(子类原型)son.prototype上面创建多余大的不必要属性,同时保持原型链不变。

This对象的理解

1.this 总是指向函数的直接调用者(而非间接调用者)

2.如果有 new 关键字, this 指向 new 出来的那个对象 在事件中, this 指向触发这个事件的对象.

3.特殊的是, IE 中的 attachEvent 中的 this 总是指向全局对象 Window