Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JS原型继承和类式继承

JS原型继承和类式继承

作者头像
庞小明
发布于 2018-03-07 09:47:41
发布于 2018-03-07 09:47:41
3.6K00
代码可运行
举报
文章被收录于专栏:pangguomingpangguoming
运行总次数:0
代码可运行

类式继承(构造函数)

JS中其实是没有类的概念的,所谓的类也是模拟出来的。特别是当我们是用new 关键字的时候,就使得“类”的概念就越像其他语言中的类了。类式继承是在函数对象内调用父类的构造函数,使得自身获得父类的方法和属性。call和apply方法为类式继承提供了支持。通过改变this的作用环境,使得子类本身具有父类的各种属性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var father = function() { 
  this.age = 52; 
  this.say = function() { 
    alert('hello i am '+ this.name +' and i am '+this.age + 'years old'); 
  } 
}
 
var child = function() { 
  this.name = 'bill'; 
  father.call(this); 
}
 
var man = new child();
man.say();

原型继承

原型继承在开发中经常用到。它有别于类继承是因为继承不在对象本身,而在对象的原型上(prototype)。每一个对象都有原型,在浏览器中它体现在一个隐藏的__proto__属性上。在一些现代浏览器中你可以更改它们。比如在zepto中,就是通过添加zepto的fn对象到一个空的数组的__proto__属性上去,从而使得该数组成为一个zepto对象并且拥有所有的方法。话说回来,当一个对象需要调用某个方法时,它回去最近的原型上查找该方法,如果没有找到,它会再次往下继续查找。这样逐级查找,一直找到了要找的方法。 这些查找的原型构成了该对象的原型链条。原型最后指向的是null。我们说的原型继承,就是将父对像的方法给子类的原型。子类的构造函数中不拥有这些方法和属性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var father = function() {
 
}
 
father.prototype.a = function() {
 
}
 
var child = function(){}
 
//开始继承
 
child.prototype = new father(); 
var man = new child(); 
man.a();

可以看到第七行实现了原型继承。很多人并不陌生这种方式。通过在浏览器中打印man我们就可以查看各个原型的继承关系。

可以看到逐级的关系child->object(father实例化的对象)->father。child是通过中间层继承了father的原型上的东西的。但是为什么中间还有一层object呢,为什么不把child.prototype = father.prototype。答案是如果这样做child和father就没有区别了。大家应该还记得在prototype中有个constructor属性,指向的是构造函数。按照正常的情况我们要把constructor的值改回来指向child的构造函数。但如果直接把father.prototype赋值给child.prototype,那么constructor应该指向谁呢?所以很显然只能通过中间层才能使得child和father保持为独立的对象。

对比

和原型对比起来,构造函数(类)式继承有什么不一样呢?首先,构造函数继承的方法都会存在父对象之中,每一次实例,都回将funciton保存在内存中,这样的做法毫无以为会带来性能上的问题。其次类式继承是不可变的。在运行时,无法修改或者添加新的方法,这种方式是一种固步自封的死方法。而原型继承是可以通过改变原型链接而对子类进行修改的。另外就是类式继承不支持多重继承,而对于原型继承来说,你只需要写好extend对对象进行扩展即可。

组合模式

另外的一种模式,是结合类继承和原型继承的各自优点来进行对父类的继承。用类式继承属性,而原型继承方法。这种模式避免了属性的公用,因为一般来说,每一个子类的属性都是私有的,而方法得到了统一。这种模式称为组合模式,也是继承类式常用到的一种方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function father() { 
  this.a = 'father'   
}
 
father.prototype.b = function() { 
   alert(this.a) 
}
 
var child = function() { 
  father.call(this) 
}
 
child.prototype = new father();

new 关键字和Obeject.create方法

在文章中,博主指出了使用new关键字的弊端。他说:“new关键字掩盖了JavaScript中真正的原型继承,使得它更像是基于类的继承。其实new关键字只是Javascript在为了获得流行度而加入与Java类似的语法时期留下来的一个残留物”。作者推荐我们使用Object.create方法创建或者实例化对象。露珠做过测试,使用new和使用object.create方法都是将对象添加到原型上去。我们可以看一下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var father = function() { 
    this.a = 'father'   
}
 
father.prototype.b = function() {alert(this.a)} 
var obj = new father();

在浏览器中打印obj,可以观察它的结构。它本身是一个对象,有自身属性,同时在其__proto__熟悉上也有b方法。在__proto__的后面有father,可以看出原型是自father来的。

那么objcet.create方法呢,我们也可以通过下面代码测试之:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var father = { 
  a: 'father', 
  b: function() { 
     alert(this.a); 
   } 
}
 
var obj = Object.create(father); 
console.dir(obj)

下面是浏览器输出的结果:

可以看到,用create的方法构造出来的对象,a属性和b方法都是在对象的原型上,也就是说我们可以通过更改father的属性动态改变obj的原型上的方法和属性,而上面通过new关键字用构造函数生成的实例,a属性是无法改变的。从这里,我们也可以看到类继承和原型基础的一些区别。

结论

原型继承比较符合js这种语言的特点。因为它本身就是js强大的原型的一部分。而类式继承,与其称它为继承方式,毋宁说是一种函数的运用技巧来模拟继承罢了。本文是卤煮的一己之见,错误偏颇在所难免,如果有之,请各位斧正。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-03-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面向对象之继承的那几种模式
往往在项目中都会看到有用class,或者OOP思想去组织业务代码,本篇只做项目中常用到的继承以及对不同继承方式的回顾,也是再次加深对继承的一些理解,希望你在项目中有些帮助和思考。
Maic
2022/07/28
2350
面向对象之继承的那几种模式
JavaScript实现继承
使用class继承非常简单。子类使用extends关键字表明继承于哪个类,并在子类中调用super(),这相当于使用call()改变this的指向。
不作声
2020/10/30
4200
JS实现继承的方式
构造函数继承的关键:在Child构造函数中执行Parent.call(this)。
用户3258338
2020/06/02
2.1K0
JS实现继承的方式
JavaScript继承的实现方式:原型语言对象继承对象原理剖析
对象的继承:A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。
周陆军
2021/08/14
8350
「思维导图学前端 」一文搞懂Javascript对象,原型,继承
去年开始我给自己画了一张知识体系的思维导图,用于规划自己的学习范围和方向。但是我犯了一个大错,我的思维导图只是一个全局的蓝图,而在学习某个知识点的时候没有系统化,知识太过于零散,另一方面也很容易遗忘,回头复习时没有一个提纲,整体的学习效率不高。意识到这一点,我最近开始用思维导图去学习和总结具体的知识点,效果还不错。试想一下,一张思维导图的某个端点是另一张思维导图,这样串起来的知识链条是多么“酸爽”!当然,YY一下就好了,我保证你没有足够的时间给所有知识点都画上思维导图,挑重点即可。
程序员白彬
2020/07/10
7870
「思维导图学前端 」一文搞懂Javascript对象,原型,继承
JS 继承的7种方法,你学会了吗?
在上一篇文章中我们讲解了原型链的机制以及原型相关的一些属性,而与原型链息息相关的就是继承了,为什么这么说呢?
小丞同学
2021/08/23
7120
​JS基础-完美掌握继承知识点
上篇文章详细解析了原型、原型链的相关知识点,这篇文章讲的是和原型链有密切关联的继承,它是前端基础中很重要的一个知识点,它对于代码复用来说非常有用,本篇将详细解析JS中的各种继承方式和优缺点进行,希望看完本篇文章能够对继承以及相关概念理解的更为透彻。
OBKoro1
2019/09/23
6030
JS原型链与继承别再被问倒了
继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实现继承则继承实际的方法.由于js中方法没有签名,在ECMAScript中无法实现接口继承.ECMAScript只支持实现继承,而且其 实现继承 主要是依靠原型链来实现的.
全栈程序员站长
2021/06/10
6530
Javascript实现完美继承实现javascript完美继承要考虑三个方面:
实现javascript完美继承要考虑三个方面: 第一步: 获取父构造函数体内的属性 解决方法: 通过 Father.call(this)实现(这里的this是子构造函数) 第二步: 根据父构造函数
zhaoolee
2018/04/19
7290
Javascript实现完美继承实现javascript完美继承要考虑三个方面:
深入理解JavaScript原型:prototype,__proto__和constructor
JavaScript语言的原型是前端开发者必须掌握的要点之一,但在使用原型时往往只关注了语法,其深层的原理并未理解透彻。本文结合笔者开发工作中遇到的问题详细讲解JavaScript原型的几个关键概念,如有错误,欢迎指正。 1. JavaScript原型继承 提到JavaScript原型,用处最多的场景便是实现继承。然而在实现继承时总有一些细节处理不到位,引起一些看起来莫名其妙的问题。比如使用下述代码: function Animal(){} Animal.prototype = {}; function
寒月十八
2018/01/30
8610
《现代Javascript高级教程》JavaScript中的原型与继承
JavaScript是一门支持面向对象编程的语言,它的函数是第一公民,同时也拥有类的概念。不同于传统的基于类的继承,JavaScript的类和继承是基于原型链模型的。在ES2015/ES6中引入了class关键字,但其本质仍然是基于原型链的语法糖。
linwu
2023/07/27
2840
《现代Javascript高级教程》JavaScript中的原型与继承
一篇JavaScript技术栈带你了解继承和原型链
在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则。
达达前端
2019/11/19
4680
[我的理解]Javascript的原型与原型链
一、原型与原型链的定义 原型:为其他对象提供共享属性的对象     注:当构造器创建一个对象,为了解决对象的属性引用,该对象会隐式引用构造器的"prototype"属性。程序通过constructor.prototype可以直接引用到构造器的"prototype"属性。并且添加到对象原型里的属性,会通过继承与所有共享此原型的对象共享。 原型链:每个由构造器创建的对象,都有一个隐式引用(叫做对象的原型)链接到构造器的"prototype"属性。再者,原型可能有一个非空隐式引用链接到它自己的原型,以此类推,这叫
sam dragon
2018/01/17
9090
[我的理解]Javascript的原型与原型链
JS 继承
用过 React的读者知道,经常用 extends继承 React.Component:
grain先森
2019/03/28
3K0
JS 继承
第158天:面向对象入门
在这里我们可以理解为创造对象的几种模式:单例模式,工厂模式,构造函数模式,原型模式等。
半指温柔乐
2018/09/11
3340
第158天:面向对象入门
Javascript的原型继承,说清楚
     一直以来对Javascript的原型、原型链、继承等东西都只是会用和了解,但没有深入去理解这门语言关于继承这方面的本质和特点。闲暇之余做的理解和总结,欢迎各位朋友一起讨论。 本文本主要从两段代码的区别说明继承: 一、第一段代码: function Parent(){ this.Name='parent'; } Parent.prototype.getName = function(){ return this.Name; } Parent.prototype.Share = [
sam dragon
2018/01/17
5560
Javascript的原型继承,说清楚
js的this、call、apply、bind、继承、原型链0.前言1.this2.call、apply、bind3.从call到继承
这些都是js基础进阶的必备了,有时候可能一下子想不起来是什么,时不时就回头看看基础,增强硬实力。
lhyt
2018/10/31
8610
【THE LAST TIME】一文吃透所有JS原型相关知识点
首先我想说,【THE LAST TIME】系列的的内容,向来都是包括但不限于标题的范围。
Nealyang
2019/11/04
1.1K0
深入浅出js实现继承的7种方式
  有些人认为JavaScript并不是真正的面向对象语言,在经典的面向对象语言中,您可能倾向于定义类对象,然后您可以简单地定义哪些类继承哪些类(参考C++ inheritance里的一些简单的例子),JavaScript使用了另一套实现方式,继承的对象函数并不是通过复制而来,而是通过原型链继承
TimothyJia
2019/11/12
2.1K0
JavaScript实现继承的6种方式
创建 Father 的实例,并赋值给 Son 的原型 Son.prototype。实现了 Son 继承 Father,
andyhu
2023/06/18
4380
相关推荐
面向对象之继承的那几种模式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验