资讯专栏INFORMATION COLUMN

javascript 中各种继承方式的优缺点

desdik / 3460人阅读

摘要:中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现。下面对各种实现方式进行分析,总结各自的优缺点。一原型继承通过改变原型对象实现继承保持构造函数和原型对象的完整性说明是继承而来的属性复用了方法优点父类的方法得到了复用。

javascript中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现。下面对各种实现方式进行分析,总结各自的优缺点。
一 原型继承
let Super = functioin(name = "eric") {
    this.name = name;
    this.getName = function() {
        return this.name;
    }
}

let Sub = function(sex = "male") {
    this.sex = sex;
}
Sub.prototype = new Super("eric");  //通过改变原型对象实现继承
Sub.prototype.constructor = Sub // 保持构造函数和原型对象的完整性
let sub1 = new Sub("male")
     sub2 = new Sub("female");

console.log(sub1.getName()); // eric
console.log(sub1.hasOwnProperty("name")) // false 说明是继承而来的属性
console.log(sub1.getName === sub2.getName) // true,复用了方法
     

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

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

二 构造函数实现继承
let Super = function(name = "eric") {
    this.name = name;
    this.getName = function() {
      return this.name;
    }
  }
  let Sub = function(name, sex) {
    Super.call(this, name);
    this.sex = sex;
  }
  let sub1 = new Sub("eric", "male");
  let sub2 = new Sub("ada", "female");
  console.log(sub1.name) // "eric"
  console.log(sub1.hasOwnProperty("name")) // true 说明不是继承而来,是自己的属性
  console.log(sub1.getName === sub2.getName) // false 方法没有得到复用

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

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

三 组合式继承
let Super = function(name = "eric") {
    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");
console.log(sub1.name); // "eric"
console.log(sub1.hasOwnProperty("name")); // true 自己的属性
console.log(sub1.getName === sub2.getName); // true 复用了方法
console.log(Sub.prototype) // { name: "eric" }
console.log(sub1) // { name: "eric", sex: "male" }

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

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

四 寄生组合式继承
let Super = function(name = "eric") {
    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);
// 当然这个地方也可以使用Object.setPrototypeOf(Sub.prototype, Super.prototype)
// 因为更改一个对象的隐士原型(__proto__)对浏览器和js引擎都是很慢对操作,所以建议使用Object.create()创建一个具有指定原型对象的新对象
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"
})

sub1.setName("ada");
console.log(sub1.getName(),sub2.getName()) // ada,eric,属性没复用,各自实例都有自己的属性。
console.log(sub1.getName === sub2.getName) // true; 复用了父类的方法
console.log(Sub.prototype.sex) // undefined
// 子类原型对象上没有父类构造函数中赋值的属性,不是组合式继承

由以上结果可以看到es6中的class只不过是一种语法糖,通过上面的验证得知符合寄生组合继承的特点,但这只是猜测,class具体都做了哪些操作还不是很清楚,后面有时间,对class做一下研究。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83717.html

相关文章

  • JavaScript深入之继承多种方式缺点

    摘要:深入系列第十五篇,讲解各种继承方式和优缺点。优点融合原型链继承和构造函数的优点,是中最常用的继承模式。寄生组合式继承为了方便大家阅读,在这里重复一下组合继承的代码组合继承最大的缺点是会调用两次父构造函数。 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎...

    JackJiang 评论0 收藏0
  • JavaScript继承

    摘要:前言作为中最重要的内容之一,继承问题一直是我们关注的重点。如果一个类别继承自另一个类别,就把这个称为的子类,而把称为的父类别也可以称是的超类。 前言 作为 JavaScript 中最重要的内容之一,继承问题一直是我们关注的重点。那么你是否清晰地知道它的原理以及各种实现方式呢 阅读这篇文章,你将知道: 什么是继承 实现继承有哪几种方式 它们各有什么特点 这里默认你已经清楚的知道构造函...

    guyan0319 评论0 收藏0
  • JavaScript之深入各种继承

    摘要:通常有这两种继承方式接口继承和实现继承。理解继承的工作是通过调用函数实现的,所以是寄生,将继承工作寄托给别人做,自己只是做增强工作。适用基于某个对象或某些信息来创建对象,而不考虑自定义类型和构造函数。 一、继承的概念 继承,是面向对象语言的一个重要概念。通常有这两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。 《JS高程》里提到:由于函数没有签名,...

    tomlingtm 评论0 收藏0
  • 深入理解JavaScript

    摘要:深入之继承的多种方式和优缺点深入系列第十五篇,讲解各种继承方式和优缺点。对于解释型语言例如来说,通过词法分析语法分析语法树,就可以开始解释执行了。 JavaScript深入之继承的多种方式和优缺点 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎,再让我...

    myeveryheart 评论0 收藏0
  • javascript一些理解

    摘要:基本类型引用类型原型构造函数上有属性,为原型对象为实例对象,每个对象上都有,而指向的是原型对象,而原型对象上有属性,指向的是上一级的原型对象。 基本类型 String ,null,undefined,number,boolean 引用类型:object 原型: function People(name,sex){ this.name=name; this.sex=sex...

    shenhualong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<