js继承的相关问题

整理了一些js继承相关的内容,如有看到这篇文章的同学,不对的地方还望指出

使用call或apply继承(构造继承)

call和apply的作用是一样的,都是改变一个函数运行时this的指向,只是两者接受的参数有些差别,这里就不多说了。

    function parent() {
        this.name = 'Aiden';
        this.say = function (){
            console.log(this.name);
        }
    }
    
    function child() {
        parent.call(this);
        this.age = 17;
    }

    var kid = new child();
    kid.say(); //Aiden

这种继承有一个缺点,child无法继承parent的原型对象,仅仅实现部分继承,如下。

    function parent() {
        this.name = 'Aiden';
        this.say = function (){
            console.log(this.name);
        }
    }

    parent.prototype.sayHello = function () {
        console.log('Hello');
    };
    
    function child() {
        parent.call(this);
        this.age = 17;
    }

    var kid = new child();
    kid.sayHello(); // Uncaught TypeError: kid.sayHello is not a function

使用prototype继承(原型链继承)

将parent的实例作为child的原型

    function parent() {
        this.name = 'Aiden';
        this.say = function (){
            console.log(this.name);
        }
    }
    
    function child() {
        this.age = 17;
    }

    child.prototype = new parent();

    var kid = new child();
    kid.say(); // Aiden

这种方式解决了上文中继承不完全的问题

    function parent() {
        this.name = 'Aiden';
        this.say = function (){
            console.log(this.name);
        }
    }
    
    function child() {
        this.age = 17;
    }

    parent.prototype.sayHello = function(){
        console.log('Hello');
    };
    
    child.prototype = new parent();

    var kid = new child();
    kid.say(); // Aiden
    kid.sayHello(); // Hello

这种方法解决了一个问题的同时衍生出了另一个问题。参考下面代码,运行结果和期望结果并不一致。
这是因为kidA和kidB继承的数组arr共用了同一块内存,push操作和赋值不一样,不会重新分配内存,所以导致了这个结果,也就是说kidA和kidB没有真正意义上的隔离。

    function parent() {
        this.name = 'Aiden';
        this.arr = [1,2,3];
        this.say = function (){
            console.log(this.name);
        }
    }
    
    function child() {
        this.age = 17;
    }

    child.prototype = new parent();

    var kidA = new child();
    kidA.name = 'Tom';
    kidA.arr.push(4);
    var kidB = new child();


    console.log(kidA.name); // Tom
    console.log(kidA.arr); // [1,2,3,4]
    console.log(kidB.name); // Aiden
    console.log(kidB.arr); // [1,2,3,4]

组合式继承

这种方式解决了上面两种的缺点

    function parent() {
        this.name = 'Aiden';
        this.arr = [1,2,3];
        this.say = function (){
            console.log(this.name);
        }
    }

    function child() {
        parent.call(this);
        this.age = 17;
    }

    child.prototype = Object.create(parent.prototype);

    var kidA = new child();
    kidA.name = 'Tom';
    kidA.arr.push(4);
    var kidB = new child();


    console.log(kidA.name); // Tom
    console.log(kidA.arr); // [1,2,3,4]
    console.log(kidB.name); // Aiden
    console.log(kidB.arr); // [1,2,3]

ES6的继承

es6多了class类的概念,可以直接使用extends继承,没有上述的这些问题。注意子类的constructor中一定要先调用super方法,否则实例化时会报错,具体可参考阮一峰老师的《ECMAScript 6 入门》。

    class human {
        constructor(){
            this.city = 'Shanghai';
        }
    }

    class man extends human{
        constructor() {
            super();
            this.sex = 'male';
            this.arr = [1,2,3];
        }
    }

    class Tom extends man {
        constructor(){
            super();
            this.name = 'Tom';
        }
    }

    let person1 = new Tom();
    console.log(person1.city); // Shanghai
    console.log(person1.name); // Tom
    console.log(person1.sex); // male
    person1.arr.push(4); // [1, 2, 3, 4]
    console.log(person1.arr);

    let person2 = new Tom();
    console.log(person2.arr); // [1, 2, 3]

猜你喜欢

转载自blog.csdn.net/weixin_41459434/article/details/83113371