继承

作者: 叫我颜先生 | 来源:发表于2022-03-13 21:59 被阅读0次

    研究学习了js内部的继承方式,以及多种方式的优点和缺点

    • 目前项目中的
    /*
     * @Description: ObjectWall
     */
    class ObjectWall extends ObjectGame {
        constructor() {
            super();
            this.type = ObjectTypeEnum.WALL;
            this.isObjectWall = true;
        }
    
        initialize(startPos, endPos, width, height, isCurving, sideMode){
            this.name = this.type + this.uuid;
        }
    }
    
    • 以前项目中的
    /*
     * @Description: ObjectWall
     */
    var ObjectWall = function (startPos, endPos, width, height, isCurving) {
        ObjectGame.call(this);
        this.type = Basic.TYPE_WALL;
    };
    
    ObjectWall.prototype = Object.assign(Object.create(ObjectGame.prototype), {
    
        constructor: ObjectWall,
    
        updateSkirtLine: function () {
            //...
        },
    }
    

    js中继承有多种方式

    1. 原型继承:子类的原型指向父类的一个实例,即子类的 protytype 指向父类实例的proto,所以子类实例就继承了父类原型上的属性和方法。
    Child.prototype = new Parent();
    

    举例

    function Foo(name = "foo") {
      this.name = name;
      this.array = [];
    }
    Foo.prototype.name = "tom";
    
    function Child() {}
    Child.prototype = new Foo();
    
    const child = new Child("child1");
    child.array.push(1);
    
    const child2 = new Child("child2");
    child2.array.push(2);
    console.log(child.constructor.array == Foo.prototype.array); //true
    console.log("child", child2.array); //[1,2]
    console.log(child2.name); //foo
    

    缺点:

    • 每个 child 实例中的 array 属性所指向的都是Foo.prototype.array,因此对于引用类型的存储都指向同一块内存,child1 和 child2 的 array 是共享的,并不是独立的。
    • 直接将子类的原型指向父类的实例,子类实例无法初始化父类构造函数上的属性。参考上例,每个 child 实例都不能给父类上的 name 属性赋值。
    1. 构造函数继承:在子类的构造函数中,通过改变父类构造函数的执行上下文,相当于做了代理。
    function Child() {
      Foo.apply(this, arguments);
    }
    Child.prototype = new Parent();
    

    举例

    function Foo(name = "foo") {
      this.name = name;
      this.array = [];
    }
    Foo.prototype.age = 18;
    
    function Child() {
      Foo.apply(this, arguments);
    }
    
    const child = new Child("child");
    child.array.push(1);
    console.log(child.name); // child
    console.log(child.age); // undefined prototype上的属性没有继承
    
    const child2 = new Child("child2");
    child2.array.push(2);
    console.log(child2.array); // [2] 独立的实例
    

    缺点

    • prototype 上的属性和方法没有继承。适合没有在父类原型链上自定义方法和属性的继承
    1. 寄生组合:需要浅拷贝父类对象,来解决不能访问父类原型属性的问题
    function Child() {
      Foo.apply(this, arguments);
    }
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Parent;
    

    举例

    function Foo(name = "foo") {
      this.name = name;
      this.array = [];
    }
    Foo.prototype.sayName = function () {
      console.log(this.name);
    };
    
    function Child() {
      Foo.apply(this, arguments);
    }
    
    Child.prototype = Object.create(Foo.prototype);
    Child.prototype.constructor = Child; //注意这一句,如果不加,子类实例的constructor指向Foo
    
    const child = new Child("child");
    child.array.push(1);
    console.log(child.name);
    
    const child2 = new Child("child2");
    child2.array.push(2);
    console.log(child2.array); // [2] 没有共享,实例里面的属性都是独立的
    child2.sayName(); // child2 可以继承父类原型上的方法与属性
    

    缺点:

    • 几乎没有,但要非找个缺点,需要浅拷贝父类的原型,浪费内存。
    1. extends继承:目前我们项目中的方式,也是es6的一些新特性方法,很好
      举例
    class Foo {
      constructor(name = "foo") {
        this.name = name;
        this.array = [];
      }
      sayName() {
        console.log(this.name);
      }
    }
    
    class Child extends Foo {
      constructor(name) {
        super(name);
      }
    }
    
    const child = new Child("child");
    child.array.push(1);
    console.log(child.name); // child
    
    const child2 = new Child("child2");
    child2.array.push(2);
    console.log(child2.array); // [2] 没有共享,实例里面的属性都是独立的
    child2.sayName(); // child2 可以继承父类原型上的方法与属性
    

    相关文章

      网友评论

          本文标题:继承

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