10.继承

101 阅读3分钟

继承就是把已经存在的不需要多次定义的东西直接拿过来使用,例如:当一个构造函数A的实例使用了构造函数B上的属性和方法,那我们就说A继承了B,A叫子类,B叫父类。

常见的继承方式:原型继承、借用构造函数继承、组合继承、类的继承语法、拷贝继承等。

原型继承

就是把子类的原型对象指向父类的实例。也就是说父类的实例就是子类的原型对象。
    优点:
        既可以继承属性,也可以继承方法

     缺点: 继承下来的属性不在自己的身上,在原型对象上; 书写的属性不能随意修改; 需要在多个地方传递参数;  注意:如果子类的原型对象上本身要书写方法,那该语句需要出现在继承语句之后,否则会被覆盖。

借用构造函数继承

就是把父类构造函数当作普通函数调用,通过call方法改变this的指向,在子类中调用。
优点:
    继承下来的属性在子类自己身上;
    可以传递任何我们想传递的参数;
缺点:
    不能继承父类的方法。
function Person(name, age) {
            this.name = name
            this.age = age 
        }
        Person.prototype.sayHi = function () {
            console.log('我是Person上的方法');
        }
        function Students(classRoom,name1,age1)  {
            this.classRoom = classRoom
            // 这里我们来调用父类构造函数
            // Person.call(this要指向的那个对象, name的一个实参, age的一个实参)
            // 现在 call() 方法中的第一个参数就是要指向的那个对象
            // 这个对象是子类的实例 就是我们的变量 s
            // 我们知道在构造函数体内 this 就是指向的实例 也就是 s变量
        Person.call(this, name1, age1)
        }

组合继承

就是原型继承和借用构造函数继承结合使用。
优点:
    既可以继承属性也可以继承我们的方法
    继承下来的属性在自己身上
    也可以在一个地方传递参数
    也可以传递任意的参数
缺点:
    就是在子类的原型对象上多了一套属性
    对我们来说没有影响
    如果你给值了就是你给的那个值
    如果没有给值就是 undefined

ES6的继承语法

ES6继承是一种新的语法,需要用到关键字extends
        class Person {
            constructor(name, age) {
                this.name = name
                this.age = age
            }
            // 定义方法
            sayHi() {
                console.log('我是父类中的方法');
            }
        }
        // 定义子类
        class Students extends Person {
            constructor(classRoom, name, age) {
                // **先书写super()**
                super(name,age)
                this.classRoom = classRoom
            }
            play() {
                console.log('我喜欢玩游戏');
            }
        }

拷贝继承

原理是利用for in将父类实例化对象上的属性赋值给子类的原型对象。
    **in 是一个关键字,可以用来检测对象中有没有指定的属性。**
      语法: 字符串 in 对象
      //不仅能判断函数体中的属性,还能判断原型对象上的属性。
    **hasOwnProperty()方法:**
      语法:实例对象.hasOwnProperty(要检测的属性名)
      //用来检测对象上有没有某个属性,但是只能检测函数体内的不能检测原型对象上的
        function Person (name, age) {
            this.name = name
            this.age = age
        }
        // 在父类的原型对象上定义一个方法
        Person.prototype.sayHi = function () {console.log(666);}
        // 定义子类
        function Students(classRoom, name, age) {
            this.classRoom = classRoom
            // 这里要实例化一个父类的对象
            const p = new Person(name, age)
            // 利用for in循环来实现
            for (let k in p) {
                // console.log(k, p[k]);
                // 就是把拷贝下来的赋值给 子类的原型对象
                Students.prototype[k] = p[k]
            }
        }
        // 实例化一个子类
        let s = new Students(2301,'Rose', 25)