美文网首页
小白的JS之路--继承

小白的JS之路--继承

作者: 阿古瓜 | 来源:发表于2018-07-18 11:49 被阅读0次

一.通过构造继承

/* 通过构造函数实现继承 */
    // 声明父类 
    function Parent (name) {
        this._name = name;
        this.hobby = ['读书', '听歌', '打羽毛球'];
    }
    // 声明父类原型方法
    Parent.prototype.getName = function () {
        return this._name;
    }
    
    // 声明子类
    function Child (name, age){
        Parent.call(this, name);    //这里是实现构造函数继承的精华
        this._age = age;
    }
    // 为子类添加原型方法
    Child.prototype.getAge = function () {
        return this._age;
    }

队长点评:
通过构造函数实现的继承,没有涉及到原型prototype,所以父类的原型方法自然不会被子类继承。而想要被子类继承就必须放在构造函数中,这样创建出来的每个实例都会单拥有一份而不能共用,这样就违背了代码复用的原则。

二.通过原型继承

/* 通过原型继承 */
    // 声明父类 
    function Parent( name ){
        this._name = name;
        this.hobby = ['读书', '听歌', '打羽毛球'];
    }
    // 声明父类原型方法
    Parent.prototype.getName = function(){
        return this._name;
    }
    
    // 声明子类
    function Child( sex ){
        this._sex = sex;
    }
    // 继承父类
    Child.prototype = new Parent();
    // 为子类添加原型方法
    Child.prototype.getSex = function(){
        return this._sex;
    }

    var instance1 = new Child();
    var instance2 = new Child();
    console.log( instance2.hobby );     //['读书', '听歌', '打羽毛球']
    instance1.hobby.push('跑步');
    console.log( instance2.hobby );     //["读书", "听歌", "打羽毛球", "跑步"]
  
    /*
      将父类的实例赋予子类的原型prototype,父类创建的实例对象
      不仅可以访问父类原型上的属性与方法,同样也可以访问从父类
      构造函数中复制的属性和方法,将这个对象赋值给子类的原型,则
      可以访问父类的原型属性与方法的同时,还可以访问父类构造函
      数中复制的属性与方法.这是原型继承原理.      
    */

队长点评:
1.由于子类通过其原型prototype对父类的实例化,而继承了父类;如果父类中的共有属性要是引用类型,就会在子类中被所有实例共用,因此一个子类的实例更改子类原型从父类构造函数中继承来的共有属性就会直接影响到其它子类。

2.由于子类实现的继承是靠其原型prototype对父类的实例化实现的,因此在创建父类的时候是无法向父类传递参数的,因而在实例化父类的时候也无法对父类构造函数内的属性进行初始化。

三.组合继承

/* 组合式继承 */
    // 声明父类 
    function Parent( name ){
        this._name = name;
        this.hobby = ['读书', '听歌', '打羽毛球'];
    }
    // 声明父类原型方法
    Parent.prototype.getName = function(){
        return this._name;
    }
    
    // 声明子类
    function Child( name, sex ){
        //构造函数继承父类name属性 
        Parent.call( this, name );
        // 子类中新增的共有属性
        this._sex = sex;
    }
    
    // 通过原型继承,子类继承父类
    Child.prototype = new Parent();
    // 为子类添加原型方法
    Child.prototype.getSex = function(){
        return this._sex;
    }
    
    var instance1 = new Child();
    var instance2 = new Child();
    console.log( instance2.hobby );     //['读书', '听歌', '打羽毛球']
    instance1.hobby.push('跑步');
    console.log( instance2.hobby );     //['读书', '听歌', '打羽毛球']
    
    console.log( instance1.__proto__.constructor === Child);    //false
    console.log( instance1.__proto__.constructor === Parent);   //true

队长点评:
子类的实例中更改父类继承下来的引用类型属性,不会影响到其它实例,并且子类实例化过程中又能又能将参数传递到父类的构造函数中.
缺点是: 一.父类的构造函数调用了二遍; 二.子类实例的原型指向的构造函数不是指向的子类构造函数而是父类的构造函数.

四.组合继承优化版

/* 组合式继承优化版 */
    // 声明父类 
    function Parent( name ){
        this._name = name;
        this.hobby = ['读书', '听歌', '打羽毛球'];
    }
    // 声明父类原型方法
    Parent.prototype.getName = function(){
        return this._name;
    }
    
    // 声明子类
    function Child( name, sex ){
        //构造函数继承父类name属性 
        Parent.call( this, name );
        // 子类中新增的共有属性
        this._sex = sex;
    }
    
    // 通过原型继承,子类继承父类
    Child.prototype =  Object.create( Parent.prototype );
    Child.prototype.constructor = Child;
    
    // 为子类添加原型方法
    Child.prototype.getSex = function(){
        return this._sex;
    }
    
    var instance1 = new Child();
    var instance2 = new Child();
    console.log( instance2.hobby );     //['读书', '听歌', '打羽毛球']
    instance1.hobby.push('跑步');
    console.log( instance2.hobby );     //['读书', '听歌', '打羽毛球']
    
    console.log( instance1.__proto__.constructor === Child);    //true
    console.log( instance1.__proto__.constructor === Parent);   //false

队长点评:
Object.create( Parent.prototype ); 创建一个中间对象实现连接
Child.prototype.constructor = Child; 改变子类原型的构造函数指向

五.多继承

// 多继承
    var mix = function(){
        var len = arguments.length, // 获取参数长度
            target = arguments[0],  // 第一个对象为目标对象
            arg;                    // 缓存参数对象
        
        // 遍历被继承的对象
        for( var i=1; i<len; i++ ){
            // 缓存当前对象
            arg = arguments[i];
            
            // 遍历被继承的对象中的属性
            for( var property in arg ){
                // 将被继承中的属性复制到目标对象中 
                target[property] = arg[property];
            }
        }
        
        // 返回目标对象
        return target
    }
    

队长点评:
这是一个浅复制,使用时请注意

六.ES6的继承

    class Parent {
        constructor(name){
            this._name = name;
        }
        
        getName(){
            return this._name;
        }
    }
    
    class Child extends Parent {
        constructor(name, age){
            super(name);
            this._age = age;
        }
        
        getAge(){
            return this._age;
        }
    }

本文实例来源于张容铭大神写的《JavaScript设计模式》

相关文章

  • 小白的JS之路--继承

    一.通过构造继承 队长点评:通过构造函数实现的继承,没有涉及到原型prototype,所以父类的原型方法自然不会被...

  • Js的继承

    js的继承 @(js)[继承, js, 前端] 组合继承是原性链继承和构造函数继承的合体,它汲取了二者各自的有点,...

  • 小白的JS之路--多态

    对长点评:在面向对象中的多态,在JavaScipt中实现起来就是这么容易。

  • JS继承

    JS中的继承 许多OO语言都支持两种继承方式:接口继承和实现继承; 因为JS中没有类和接口的概念 , 所以JS不支...

  • 会计学小白成长之路——顺序集

    会计学小白成长之路1 会计学小白成长之路2 会计学小白成长之路3 会计学小白成长之路4 会计学小白成长之路5 会计...

  • #js继承

    js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承)类式继承(构造函数间的继承) 类式继承是...

  • 小白的JS之路--深拷贝

    一. 先从浅拷贝开始 二.开始我们真正的深拷贝

  • js继承遇到的小问题

    这两天在看js继承方面,它不像OC那种传统的类继承。js继承方式还是挺多的。比如:原型继承、原型冒充、复制继承 原...

  • JS中继承的实现

    JS中继承的实现 #prototype (js原型(prototype)实现继承) 全局的Function对象没有...

  • JavaScript 10

    js继承的概念 1.通过原型链方式实现继承(对象间的继承) 2.类式继承(构造函数间的继承) 由于js不像Java...

网友评论

      本文标题:小白的JS之路--继承

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