zoukankan      html  css  js  c++  java
  • javascript 中各种继承方式的优缺点 (转)

    javascript中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现。下面对各种实现方式进行分析,总结各自的优缺点。

    一 原型继承

    let Super = functioin(name) {
        this.name = name;
        this.setName = (newName) => {
            this.name = name;
        };
        this.getName = () => {
            return this.name;
        }
    }
    
    let Sub = function(sex) {
        this.sex = sex;
    }
    Sub.prototype = new Super('eric');  //通过改变原型对象实现继承
    let sub1 = new Sub('male')
         sub2 = new Sub('female');
    
    sub1.setName('ada');
    // 这里必须通过setName方法来修改继承来的name属性。
    // 如果通过sub1.name== 'ada',就打不到目的,因为此时sub1对象上没有name属性,
    // 这样等于为该对象添加了新的属性,而不是修改继承而来的name属性。
    console.log(sub2.name); // ada,可见此sub2的name也会被修改掉
    console.log(sub1.getName === sub2.getName) // true,复用了方法
         

    优点:父类的方法(getName)得到了复用。

    缺点:同理父类的属性(name)也是复用,即子类实例没有自己的属性。

    二 构造函数实现继承

    let Super = function(name) {
        this.name = name;
        this.getName = () => {
            return this.name;
        }
    }
    let Sub = function(sex,name) {
        Super.call(this,name); // 调用父类方法为子类实例添加属性
        this.sex = sex;
    }
    
    let sub1 = new Sub('male','eric'),
         sub2 = new Sub('female','eric');
    sub1.name = 'ada';
    console.log(sub2.name); // eric,实例的属性没有相互影响
    
    console.log(sub1.getName === sub2.getName); // false,可见方法没有复用
    

    优点:子类的每个实例都有自己的属性(name),不会相互影响。

    缺点:但是继承父类方法的时候就不需要这种特性,没有实现父类方法的复用。

    三 组合式继承

    let Super = function(name) {
        this.name = name;
    }
    Super.prototype = {
        constructor: Super, // 保持构造函数和原型对象的完整性
        getName() {
            return this.name;
        }
    }
    let Sub = function(sex) {
        Super.call(this,'eric'); //继承父类属性
        this.sex = sex;
    }
    Sub.prototype = new Super('eric'); //继承父类方法
    Sub.prototype.constructor = Sub;
    let sub1 = new Sub('male'),
        sub2 = new Sub('female');
    // 可以按上述两种方法验证,复用了父类的方法,实例没有复用,达到目的

    优点:继承了上述两种方式的优点,摒弃了缺点,复用了方法,子类又有各自的属性。

    缺点:因为父类构造函数被执行了两次,子类的原型对象(Sub.prototype)中也有一份父类的实例属性,而且这些属性会被子类实例(sub1,sub2)的属性覆盖掉,也存在内存浪费。

    四 寄生组合式继承

    let Super = function(name) {
        this.name = name;
    }
    Super.prototype = {
        constructor: Super,
        getName() {
            return this.name;
        }
    }
    let Sub = function(sex,name) {
        Super.call(this,name);
        this.sex = sex;
    }
    // 组合继承的缺点就是在继承父类方法的时候调用了父类构造函数,从而造成内存浪费,
    // 现在只要解决了这个问题就完美了。那在复用父类方法的时候,
    // 使用Object.create方法也可以达到目的,没有调用父类构造函数,问题解决。
    Sub.prototype = Object.create(Super.prototype);
    Sub.prototype.constructor = Sub;

    五 es6中的class

     
    class Super() {
        constructor(props = { name: 'eric' }) {
            this.name = props.name;
        }
        setName(name) {
            this.name = name;
        }
        getName() {
            return this.name;
        }
    }
    class Sub extends Super {
        constructor(props) {
            super(props = { sex: 'male' }); // 创建实例,继承父类属性和方法
            this.sex = props.sex;
        }
    }
    let sub1 = new Sub({
        name: 'eric',
        sex: 'male'
    })
    let sub2 = new Sub({
        name: 'eric',
        sex: 'female'
    })
  • 相关阅读:
    ConcurrentHashMap
    Linux中如何开启8080端口供外界访问 和开启允许对外访问的端口8000
    CentOs 7 Linux系统下我的/etc/sysconfig/路径下无iptables文件
    CentOS7开启SSH服务
    Centos7下Samba服务器配置
    CentOS7(Linux)网络yum源配置
    Linux(Centos7)中配置Java环境变量
    SpringAOP-什么是面向切面编程?
    Swagger Demo
    自定义个Bean名称生成策略, 解决不同包下同名类问题/AnnotationBeanNameGenerator
  • 原文地址:https://www.cnblogs.com/linzaizai/p/7529890.html
Copyright © 2011-2022 走看看