美文网首页
js中的继承

js中的继承

作者: 原来如此scater | 来源:发表于2019-03-18 23:33 被阅读0次

    上篇说了js的设计模式,现在再说说继承(不理解设计模式的可以看上篇)。
    1、原型链

    function Child(){
        this.name= 'scater';
    }
    function Parent(){
        this.age= 29;
    }
    //继承了 SuperType
    Child.prototype = new Parent();
    Parent.prototype.getAge= function (){
        return this.age;
    };
    const child1 = new Child();
    console.log(child1.getAge()); //29
    

    缺点:引用类型属性被实例共享;创建子类实例时,无法向父类构造函数传参。
    2、借用构造函数

    function Child(){
        this.name= 'scater';
        Parent.call(this); // call和apply都可以
    }
    function Parent(){
        this.age= 29;
        this.getAge= function (){
            return this.age;
        }
    };
    const child1 = new Child();
    console.log(child1.getAge()); //29
    

    实例并不是父类的实例,只是子类的实例;只能继承父类的实例属性和方法,不能继承原型属性/方法;无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
    3、组合继承

    function Parent(){
        this.age= 29;
        this.getAge= function (){
            return this.age;
        }
    };
    function Child(){
        this.name= 'scater';
        Parent.call(this); // call和apply都可以
    }
    Child.prototype = new Parent();
    Child.prototype.constructor = Child; // 将构造函数指向Child
    Parent.prototype.getName = function (){
        return this.name;
    };
    const child1 = new Child();
    console.log(child1.getAge(), child1.getName ()); //29, 'scater'
    

    可以继承父级实例属性/方法,也可以继承父级原型属性/方法;但是调用了两次父类构造函数,生成了两份实例。
    4、原型式继承

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    var person = {
        name: "scater",
        friends: ["tom", "Lee"]
    };
    // 利用object继承
    const anotherPerson = object(person);
    // 给子类添加自有属性
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    console.log (anotherPerson.name, anotherPerson.friends);  // Greg ["tom", "Lee", "Rob"]
    

    ES5 通过新增 Object.create() 方法规范化了原型式继承。这个方法接收两个参数:一
    个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。

    var anotherPerson = Object.create(person);
    // 给子类添加自有属性
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    console.log (anotherPerson.name, anotherPerson.friends);  // Greg ["tom", "Lee", "Rob"]
    

    在没有必要创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原型式
    继承是完全可以胜任的。但是包含引用类型值的属性始终都会共享相应的值,就像使用原型模
    式一样。
    5、寄生式继承

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    function createAnother(original){
        var clone = object(original); //通过调用函数创建一个新对象
        clone.sayHi = function(){ //以某种方式来增强这个对象
            console.log("hi");
        };
        return clone; //返回这个对象
    }
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi(); //"hi"
    

    在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。
    6、寄生组合式继承(推荐)

    function Parent(){
        this.age= 29;
    }
    function Child(name){
      Parent.call(this);
      this.name = name;
    }
    (function(){
      // 创建一个没有实例方法的类
      var Super = function(){};
      Super.prototype = Parent.prototype;
      //将实例作为子类的原型
      Child.prototype = new Super();
    })();
    
    Child.prototype.constructor = Child; // 将构造函数指向Child
    const scater= new Child('scater');
    console.log(scater.name, scater.age); // scater 29
    

    7、ES6 Class类的继承

    class Parent {
      constructor() {
        this.age = 29;
      }
    }
    class Child extends Parent {
      constructor(name) {
        super(); // 在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。
        this.name = name;
      }
    }
    const scater = new Child('scater');
    console.log(scater.name, scater.age); // scater 29
    

    ES6 的继承机制,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。

    相关文章

      网友评论

          本文标题:js中的继承

          本文链接:https://www.haomeiwen.com/subject/aipimqtx.html