• JavaScript中的继承


    JavaScript中的继承有多种实现,我们一步步来,层层深入下。

    一、 原型继承,又称类式继承。

      实现:将父类的示例赋值给子类的原型对象prototype。

      代码示例: 

    function SuperType() {
        this.prop = 'super';
    };
    
    SuperType.prototype.getName = function () {
        console.log(this.prop);
    };
    
    function SubType() {
        this.subProp = 'sub';
    };
    
    SubType.prototype = new SuperType(); // 原型继承的精华
    
    var sub = new SubType();
    sub.getName(); // super
    console.log(sub.subProp) // sub

      解释:将父类的示例赋值给子类的原型对象prototype,则子类的原型对象不仅会拥有父类构造函数中的所有属性和方法,还会拥有父类原型对象中的属性和方法。

      因此在实例化子类对象时,子类不仅会执行子类的构造函数,拥有子类构造函数中的属性和方法,还会继承来自子类原型上的属性和方法,

      而子类原型上的属性和方法已通过 SubType.prototype = new SuperType() 拥有了父类构造函数和父类原型上的属性和方法,

      从而子类也拥有了父类构造函数和父类原型上的属性和方法。。。

      缺点:

        1. 如果父类中的共有属性是引用类型,就会在子类实例中被所有实例公用。

        2. 由于子类实现的继承是靠其原型对父类实例化实现的,因此在创建父类的时候是无法像父类传参的。  

    function SuperType() {
        this.arr = ['aa', 'bb'];
    };
    
    function SubType() {};
    
    SubType.prototype = new SuperType();
    
    var sub1 = new SubType();
    var sub2 = new SubType();
    sub1.arr.push('cc');
    
    console.log(sub1.arr); // ["aa", "bb", "cc"]
    console.log(sub2.arr); // ["aa", "bb", "cc"]

    二、构造函数继承

      实现:在子类构造函数中执行一遍父类的构造函数。

      代码实例:

    function SuperType(prop) {
        this.superProp = prop;
        this.arr = ['aa', 'bb'];
    };
    
    SuperType.prototype.getArr = function () {
        console.log(this.arr);
    };
    
    function SubType(prop) {
        SuperType.call(this, prop); // 可以传参
    };
    
    var sub1 = new SubType('super1');
    var sub2 = new SubType('super2');
    sub1.arr.push('cc');
    
    console.log(sub1.superProp) // super1
    console.log(sub2.superProp) // super2
    
    console.log(sub1.arr); // ["aa", "bb", "cc"]
    console.log(sub2.arr); // ["aa", "bb"]  arr没有被实例共用
    
    console.log(sub1.getArr) // undefined  原型上的属性或方法无法继承

      虽然这种方式解决了原型继承出现的问题,但这种方式也是有明显的缺点的。

      缺点:由于实现继承没有涉及到原型prototype,所以父类的原型方法自然不会被子类继承。而如果想要实现继承,则必须将方法放在构造函数中,

         但这样创建出来的每个实例都会单独拥有一份而不会共用,就会违背代码复用的原则。

    三、混合继承

      实现:将上述两种方式混合使用,解决上述两种方式出现的问题。

      代码示例:

    function SuperType(prop) {
        this.superProp = prop;
        this.arr = ['aa', 'bb'];
    };
    
    SuperType.prototype.getArr = function () {
        console.log(this.arr);
    };
    
    function SubType(prop) {
        SuperType.call(this, prop);
    };
    
    SubType.prototype = new SuperType();
    
    var sub1 = new SubType('super1');
    var sub2 = new SubType('super2');
    sub1.arr.push('cc');
    
    console.log(sub1.superProp) // super1
    console.log(sub2.superProp) // super2
    
    sub1.getArr() // ["aa", "bb", "cc"]
    sub2.getArr() // ["aa", "bb"]

      同样,这种继承方式也是有缺点的,由于在使用构造函数继承时我们执行了一遍父类的构造函数,在原型继承的时候我们又执行了一遍父类的构造函数,

      这样就使得父类的构造函数被执行了两遍。看来这也不是最完美的实现继承的方式。

      那么,到底存不存在最完美的实现继承的方式呢?

      后面会继续补充~~

  • 相关阅读:
    安装 macbook 双系统( OS X 和 Ubuntu )
    微信小程序初探
    [Javascript] Promise
    [AS/400] 基本概念
    [AS/400] Control Language(CL) 基本概念
    [AS/400] Control Language
    [github] 创建个人网页
    [tools] sublime 使用记录
    [Java] TreeMap
    exe转msi
  • 原文地址:https://www.cnblogs.com/zhangxiaos/p/6418975.html
Copyright © 2020-2023  润新知