js继承的几种实现方式

JS继承的几种实现方式

首先,我们定义一个父类:

 function Person(myName, myAge) {
        this.name = myName;
        this.age = myAge;
        this.arr = [1,2];
        this.say = function () {
            console.log(this.name, this.age);
        }
    }
 Person.prototype.eat = function () {
         console.log("eat");
    };

方式一(原型链继承):

将父类的实例对象作为子类的原型对象

function Student(myName, myAge, myScore) {
        this.score = myScore;
        this.study = function () {
            console.log("day day up");
        }
    }
    Student.prototype = new Person();
    Student.prototype.constructor = Student;
    let stu1 = new Student();
    let stu2 = new Student();
    stu1.arr.push(3);
    console.log(stu2.arr); // [1,2,3]

缺点:

  1. 创建子类实例时,无法向父类构造函数传参
  2. 来自子类的原型对象中的属性被所有实例共享,导致引用类型的属性会被多个实例修改

方式二(借用构造函数继承):

将Person的this指向Student的实例对象stu,解决了传参问题

function Student(myName, myAge, myScore) {
            Person.call(this, myName, myAge); 
            this.score = myScore;
            this.study = function () {
                console.log("day day up");
            }
        }
        let stu = new Student("ww", 19, 99);
        console.log(stu.score); // 99
        stu.say(); // ww 19
        stu.eat(); // 报错:不存在这个函数

缺点:

  1. 只能继承父类的实例属性和方法,不能继承原型属性/方法
  2. 本质上是复制父类的实例属性和方法给子类,两个函数没有关系,没有实现函数的复用,性能不高

方式三(组合继承):

组合继承是方式一和方式二的结合,原型链实现对原型属性和方法的继承,借用构造函数来实现实例属性和方法的继承。

function Student(myName, myAge, myScore) {
		Person.call(this, myName, myAge); 
        this.score = myScore;
        this.study = function () {
            console.log("day day up");
        }
    }
    Student.prototype = new Person();
    Student.prototype.constructor = Student;

这是一种比较常用的继承方式,缺点是调用了两次父类的构造函数,使得子类的实例对象和原型对象中有两份相同的属性和方法

方式四(寄生组合继承):

使用Object.create()替代new

function Student(myName, myAge, myScore) {
		Person.call(this, myName, myAge); 
        this.score = myScore;
        this.study = function () {
            console.log("day day up");
        }
    }
	var prototype = Object.create(Person.prototype); //创建对象
	prototype.constructor = Student; //增强对象
	Student.prototype = prototype; //指定对象

通过Object.create()创建的函数,并没有去调用构造函数,因此构造函数上的属性和方法不会继承到Object.create创建的实例中,只有原型对象中的属性和方法。解决了组合继承中调用两次父类的构造函数的问题

方式五(ES6继承):

简化了代码,实现原理同寄生组合继承

Class Student extends Person{
	   Constructor(myName, myAge, myAge){
	  	   this.score = myScore;
		   super(myName, myAge)}
	}

你可能感兴趣的:(js)