原生Javascript实现继承方式及其优缺点详解

 更新时间:2021年07月21日 11:32:40   作者:ClarenceEz  
JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一,那么这篇文章主要给大家介绍了关于原生Javascript实现继承方式及其优缺点的相关资料,需要的朋友可以参考下

前言

最近在复习javascript的一些基础知识,为开启新的征程做准备。所以开始记录一些自己学习的内容。

那今天的主题是 js的原生继承方式

废话少说,上代码!

首先是我们的父类代码。

在这里我们创建一个Person的类作为父类,它的构造函数需要2个参数name和age。

然后我们在它的原型上添加一个sayHi的方法。

//父类
function Person (name, age) {
    this.name = name || 'no name';
    this.age = age || 0;
}

Person.prototype.sayHi = function () {
    console.log('Hi, I\'m ' + this.name + ' and i\'m ' + this.age + ' years old!');
}

var p = new Person('A',20);
p.sayHi();//Hi, I'm A and i'm 20 years old!

原型继承

//原型继承
function Teacher(){
}

Teacher.prototype=new Person('B',22);
Teacher.prototype.constructor=Teacher;

var t = new Teacher();
t.sayHi();//Hi, I'm B and i'm 22 years old!
console.log(t instanceof Person);//true
console.log(t instanceof Teacher);//true

优点

从上面的代码来看,Teacher 的实例拥有了 Person 的属性和方法。并且实例对象既是 Person的实例也是 Teacher的实例。而且这种继承方式特别的简单。

缺点

我们可以很容易的就发现Teacher类的 name和 age是固定的,都是name=B和age=22,换句话说就是我们无法实现按照我们的意愿给父类的构造函数传参。并且一个我们不能给一个 Teacher 指定多个原型,也就是没法 多继承。然后我们看下下面这段代码:

var t1 = new Teacher();
var t2 = new Teacher();
Teacher.prototype.name = "C";
t1.sayHi();//Hi, I'm C and i'm 22 years old!
t2.sayHi();//Hi, I'm C and i'm 22 years old!

上面这段代码中我们可以看到当原型中的属性或者方法被改变时,所有的子类实例的属性和方法也会跟着被改变,也就是原型继承的另一个缺点:所有子类共享同一个原型对象

这里说到了原型,我很早之前也写过一个关于原型的随笔,不过可能也是有些模糊,现在的理解和当时有所不同,我会在后面重新写一篇关于原型的随笔。(写好了我会附上连接)

构造函数继承

//构造函数继承
function Teacher (name, age) {
    Person.call(this, name, age);
}

var t1 = new Teacher('B', 22);
var t2 = new Teacher('C', 30);
console.log(t1.name);//B
console.log(t2.name);//C
console.log(t1 instanceof Person);//false
console.log(t1 instanceof Teacher);//true
t1.sayHi();//TypeError: t1.sayHi is not a function
t2.sayHi();//TypeError: t1.sayHi is not a function

优点

相对于 原型继承 , 构造函数继承解决了所有的子类实例共享统一原型的问题,也可以给父类的构造函数传参,并且我们可以在子类的构造函数中调用多个父类的构造函数,实现所谓的多继承(这里的多继承是指子类通过call,apply等方法去调用父类的构造函数使其拥有父类的属性和方法,但是js中一个函数对象只存在一个 prototype,所以其实我们没法通过原型链的形式去体现出多继承)

缺点

上面的代码中我们可以看出创建的实例只是 子类的实例 并不是 父类的实例 ,不能直观的体现出继承,这种继承方式也无法继承父类的原型上的属性和方法。

组合式继承

//组合式继承
function Teacher (name, age) {
    Person.call(this, name, age);
}

Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;


var t1 = new Teacher('B', 22);
var t2 = new Teacher('C', 30);
Teacher.prototype.name = "D";
console.log(t1.name);//B
console.log(t2.name);//C
t1.sayHi();//Hi, I'm B and i'm 22 years old!
t2.sayHi();//Hi, I'm C and i'm 30 years old!
console.log(t1 instanceof Person);//true
console.log(t1 instanceof Teacher);//true

组合式继承就是结合了原型继承和构造函数继承的优点,解决了两种方式存在的一些缺点。但是我们会发现每当我们去创建一个子类实例的时候都会去创建一个父类的实例,尽管父类实例不是同一个实例(内存地址不一样),但是他们其实属性和方法上完全一致,所以我们通过下面这种(寄生式组合继承)方式完善它,以避免不必要的实例构造。

寄生式组合继承

//寄生式组合继承
function Teacher (name, age) {
    Person.call(this, name, age);
}

Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;


var t1 = new Teacher('B', 22);
var t2 = new Teacher('C', 30);
Teacher.prototype.name = "D";
console.log(t1.name);//B
console.log(t2.name);//C
t1.sayHi();//Hi, I'm B and i'm 22 years old!  
t2.sayHi();//Hi, I'm C and i'm 30 years old!
console.log(t1 instanceof Person);//true
console.log(t1 instanceof Teacher);//true 

上面的方式解决了我们没创建一个子类实例都去创建一个父类实例的问题,这也是最为常用的一种js的继承方式,如果我们通过Babel去把ES6中的class的继承转成ES5的代码,我们会发现就是用的寄生式组合继承。

总结

到此这篇关于原生Javascript实现继承方式及其优缺点的文章就介绍到这了,更多相关原生Javascript继承方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Javascript脚本获取form和input内容的方法(两种方法)

    Javascript脚本获取form和input内容的方法(两种方法)

    随着js的发展,许多的网页数据处理完全可以由js脚本解决,而不需要发送到服务器,这里分享两种Javascript脚本获取form和input内容的方法,感兴趣的朋友跟随小编一起看看吧
    2023-05-05
  • js 生成密匙流 脚本代码

    js 生成密匙流 脚本代码

    js 生成密匙流 脚本代码...
    2007-09-09
  • 如何在微信小程序中实现Mixins方案

    如何在微信小程序中实现Mixins方案

    这篇文章主要给大家介绍了关于如何在微信小程序中实现Mixins方案的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用微信小程序具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • js里的prototype使用示例

    js里的prototype使用示例

    Object对象是common的原型,Object对象的属性和方法复制到了common上
    2010-11-11
  • JS实现同一个网页布局滑动门和TAB选项卡实例

    JS实现同一个网页布局滑动门和TAB选项卡实例

    这篇文章主要介绍了JS实现同一个网页布局滑动门和TAB选项卡效果,通过简单的自定义切换函数setTab实现页面元素的遍历及属性切换的功能,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • JS字符串转GBK编码超精简实现详解

    JS字符串转GBK编码超精简实现详解

    JS中GBK编码转字符串是非常简单的,但反过来,字符串转GBK编码却没这么简单。接下来本文就将带大家一起康康JS如何实现字符串转GBK编码,需要的可以参考一下
    2022-08-08
  • 解决Babylon.js中AudioContext was not allowed to start异常问题

    解决Babylon.js中AudioContext was not allowed&nbs

    这篇文章主要介绍了解决Babylon.js中AudioContext was not allowed to start异常问题方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 微信小程序骨架屏的实现方法

    微信小程序骨架屏的实现方法

    本文主要介绍了微信小程序骨架屏的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • uniapp开发微信小程序自定义顶部导航栏功能实例

    uniapp开发微信小程序自定义顶部导航栏功能实例

    uni-app是一个使用Vue.js开发跨平台应用的前端框架,下面这篇文章主要给大家介绍了关于uniapp开发微信小程序自定义顶部导航栏功能的相关资料,文中通过图文以及示例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • Javascript 个人笔记(没有整理,很乱)

    Javascript 个人笔记(没有整理,很乱)

    Javascript 个人笔记(没有整理,很乱)...
    2007-07-07

最新评论