有关JS的继承,看这一篇就够了。

181 阅读2分钟

Javascript现在一共有7种继承方式,看看有哪些叭。

原型链继承

function Parent() {
            this.name = 'pyx'
        }

        Parent.prototype.getName = function () {
            console.log(this.name);
        }

        function Child() {

        }
        
        //主要精髓所在
        Child.prototype = new Parent();
        Child.prototype.constructor = Child

        let wyt = new Child();
        wyt.getName()//'pyx'

原型链继承缺点
1.每个实例对引用类型属性的修改都会被其他的实例共享,就是说修改wyt的name,导致后面新的子类wyh1、wyt2的名字都会变化。
2.创建Child子类实例时,无法向Parent父类传参,这样就会使子类实例没法定义自己的属性,比如说名字,wyt永远只能叫pyx。

构造函数继承

function Parent() {
            this.names = ['pyx', 'father']
        }

        Parent.prototype.getName = function () {
            console.log(this.names);
        }

        function Child() {
            //精髓
            Parent.call(this)
        }

        let wyt = new Child()
        wyt.names.push('wyt')
        console.log(wyt.names);//['pyx','father','wyt']
        // wyt.getName()//报错,原型链上函数的不能继承给子类

        let wyt1 = new Child();
        wyt1.names.push('daughter')
        console.log(wyt1.names);//['pyx','father','daughter']

优点
1.解决了每个实例对引用类型属性的修改都会被其他的实例共享的问题。
2.子类可以向父类传参,也就是new一个新的子类的时候,可以直接赋值。

缺点
1.无法复用父类的公共函数。
2.每一次子类构造实例都得执行一次父类函数。

组合式继承

 function Parent(name) {
            this.name = name
            this.body = ['foot', 'hand']
        }

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

        Child.prototype = new Parent()
        Child.prototype.constructor = Child

        let wyt = new Child('wyt', 22)
        wyt.body.push('chest')
        console.log(wyt.name, wyt.age);//wyt  22
        console.log(wyt.body);//[foot,hand,chest]

        let wyt1 = new Child('wyt1', 22)
        wyt1.body.push('chest1')
        console.log(wyt1.name, wyt1.age);//wyt1 22
        console.log(wyt1.body);//[foot,hand,chest1]

优点
1.解决了每个实例对引用类型属性的修改都会被其它的实例共享的问题。
2.子类可以向父类传参。
3.可实现父类方法的复用。

缺点
需要执行两次父类函数,第一次是 Child.prototype = new Parent(),第二次是 Parent.call(this,name),从而造成不必要的浪费。

原型式继承

 function Parent(obj) {
            function Child() { };
            Child.prototype = obj;
            return new Child()
        }

        let father = {
            name: 'pyx',
            body: ['foot', 'hand']
        }

        let wyt = Parent(father)
        let wyt1 = Parent(father)

        console.log(wyt);
        wyt.body.push('chests')
        console.log(wyt1);

缺点
同原型链继承一样,每个实例对引用类型属性的修改都会被其它的实例共享。

寄生式继承

function Parent(obj) {
            //代替原型式继承的Parent
            let clone = Object.create(obj);
            clone.getName = function () {
                console.log('pyx');
            }
            return clone
        }

优点
通过Parent就可以在创建对象的时候,把对象方法也通过此种方式继承。

缺点
同借用构造函数一样,无法复用父类函数,每次创建对象都会创建一遍方法。

寄生组合式继承

 function inheritPrototype(Parent, Child) {
            //创建父类原型的一个副本,把副本赋值给子类原型
            Child.prototype = Object.create(Parent.prototype);
            Child.prototype.constructor = Child;
        }

        function Parent(name) {
            this.name = name;
        }

        Parent.prototype.getName = function () {
            console.log(this.name);
        }

        function Child(color) {
            Parent.call(this, 'pyx')
            this.color = color;
        }

        inheritPrototype(Parent, Child)

        let wyt = new Child('red')
        console.log(wyt.name);

优点
不必为了指定子类型的原型而调用父类型的构造函数。

ES6 class继承

class Parent {
            constructor(name) {
                this.name = name
            }
            getName() {
                console.log(this.name);
            }
        }

        class Child extends Parent {
            constructor(name, color) {
                //调用父类的构造函数,相当于获得父类的this指向---constructor(name)
                super(name)
                this.color = color
            }
            logName() {
                //继承Parent里的函数
                super.getName()
            }
        }

        console.log(new Child('pyx').name);
        console.log(new Child('pyx').logName());


记录记录!