JavaScript面向对象——深入理解默认的继承方式原型链
描述:
正如我们所了解,JavaScript中的每个函数中都有一个指向某一对象的prototype属性。该函数被new操作符调用时会创建并返回一个对象,并且该对象中会有一个指向其原型对象的秘密链接,通过该秘密链接(__proto__),我们就可以在新建的对象中调用相关原型对象的方法和属性。
而原型对象自身也具有对象固有的普遍特征,因此本身也包含了指向其原型的链接,由此就形成了一条链,即我们所说的原型链。
如下图所示:在对象A的一系列属性中,有一个叫__proto__的隐藏属性,它指向了另外一个对象B。而B的__proto__属性又指向了对象C,以此类推,直至链条末端的Object对象,该对象是JavaScript的最高级对象,语言中所有对象都必须继承自它。
意义:
在某个属性不存在对象A中,而存在对象B中时,依然可以将它当做A的属性来访问,进而实现代码的重用。
举例说明:
function Shape() {this.name = 'Shape';this.toString = function() {return this.name;};}function TwoDShape() {this.name = '2D shape';}function Triangle(side, height) {this.name = 'Triangle';this.side = side;this.height = height;this.getArea = function() {return this.side * this.height/2;}}// 继承实现TwoDShape.prototype = new Shape();Triangle.prototype = new TwoDShape();// 当我们对对象的prototype属性进行完全替换时,需要重置这些对象的constructor属性。TwoDShape.prototype.constructor = TwoDShape;Triangle.prototype.constructor = Triangle;// 验证是否已经实现继承var my = new Triangle(5, 10);console.log(my.toString());// 运行结果为:Triangle
解释:
当我们在用Triangle()构造器创建的实例调用构造器不存在的toString()方法时,JavaScript引擎究竟做了什么?
①:遍历my对象中的所有属性,但没有找到一个叫做toString()的方法。
②:查看my.__proto__所指向的对象,该对象是继承关系构建过程中由new TwoDShape()所创建的实体。
③:JavaScript引擎在遍历TwoShape实体的过程中依然不会找到toString方法,这时候,__proto__属性所指向的实体是new Shape()所创建的实体。
④:在new Shape()创建的实体对象中找到toString()方法。
⑤:toString()方法在my对象中调用,并且其this指向my。
继承后的一些验证:
①:my的构造函数是:my.constructor === Triangle; 运行结果:ture.
②:my对象同时是上述三个构造器的实例,以下运行结果均为true,即:my同时是三个构造器的实例
my instanceof Shape; my instanceOf TwoDShape; my instanceOf Triangle;
扩展:将共享属性迁移到原型中去
背景描述:当我们用某一个构造器创建对象时,其属性就会被添加到this中去。并且当被添加的属性实际上不会随着实体改变时,这种做法就会显得很没有效率。比如在上面的示例中,Shape()构造器是这样定义的:
function Shape(){this.name = 'Shape';
}
这种实现即意味着我们用new Shape()创建的每个实体都会拥有一个全新的name属性,并在内存中拥有自己独立的存储空间。
解决办法:将name属性移到原型上去,这样一来,所有实体就可以共享这个属性:
function Shape(){};
Shape.prototype.name = 'Shape';
将name移到prototype上后,用new Shape()创建对象时,name属性就不再是新对象的私有属性了,而是被添加到了该对象的原型中,这样做的前提是该属性是不可变的,对象的共享方法就非常适合这种共享形式。
下面对以上的例子进行改造,把符合条件的方法和属性移到原型中去。
// constructorfunction Shape() {}// argument prototypeShape.prototype.name = 'Shape';Shape.prototype.toString = function() {return this.name;};// another constructorfunction TwoDShape() {}// take care of inheritanceTwoDShape.prototype = new Shape();TwoDShape.prototype.constructor = TwoDShape;//argument prototypeTwoDShape.prototype.name = '2D shape';// another constructorfunction Triangle(side, height) {this.side = side;this.height = height;}// take care of inheritanceTriangle.prototype = new TwoDShape();Triangle.prototype.constructor = Triangle;// argument prototypeTriangle.prototype.name = 'Triangle';Triangle.prototype.getArea = function() {return this.side * this.height/2;}// 验证是否已经实现继承var my = new Triangle(5, 10);console.log(my.toString());// 运行结果为:Triangle
在调用my.toString()时,主要区别是查找操作将更多地发生在Shape.prototype中,而不再需要像前面示例中那样,到由new Shape()所创建的实体对象中查找。
JavaScript面向对象——深入理解默认的继承方式原型链相关推荐
- JavaScript面向对象——深入理解寄生组合继承
JavaScript面向对象--深入理解寄生组合继承 之前谈到过组合继承,会有初始化两次实例方法/属性的缺点,接下来我们谈谈为了避免这种缺点的寄生组合继承 寄生组合继承: 思路:组合继承中,构造函数继 ...
- 一篇JavaScript技术栈带你了解继承和原型链
作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...
- 深入理解 js 之继承与原型链
原型链与继承 当谈到继承时,JavaScript 只有一种结构:对象.每个实例对象(object )都有一个私有属性(称之为proto)指向它的原型对象(prototype).该原型对象也有一个自己的 ...
- (二)Javascript面向对象编程:构造函数的继承
Javascript面向对象编程:构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承&q ...
- JavaScript原型彻底理解2---继承中的原型链
一.继承的概念 继承是所有的面向对象的语言最重要的特征之一.大部分的oop语言的都支持两种继承:接口继承和实现继承.比如基于类的编程语言Java,对这两种继承都支持.从接口继承抽象方法 (只有方法签名 ...
- JavaScript之继承(原型链)
JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...
- JS中对象的四种继承方式:class继承、原型链继承、构造函数继承、组合继承(构造函数和原型链继承的结合)
前言 才发现之前没有对JavaScript中的继承做过总结,不过看得到是不少,接下来就对这几种继承方式做一下总结. class继承 class继承是ES6引入的标准的继承方式. ES6引入了class ...
- ES5常用的组合继承及原型链理解
ES5常用的组合继承及原型链理解 <!DOCTYPE html> <html lang="en"><head><meta charset= ...
- 【JS继承】JS继承之原型链继承
自我介绍:大家好,我是吉帅振的网络日志:微信公众号:吉帅振的网络日志:前端开发工程师,工作4年,去过上海.北京,经历创业公司,进过大厂,现在郑州敲代码. JS继承专栏 1[JS继承]什么是JS继承? ...
最新文章
- define##的作用
- cvc降噪和主动降噪_降噪蓝牙耳机哪款好?300内建议入手的五款主动降噪蓝牙耳机...
- LeetCode 759. 员工空闲时间(排序)
- ORA-04063: view DAILY.TMP_TBX_100_0_S4 有错误
- 创建react应用程序_如何将React应用程序部署到Netlify
- 虚拟键码对照表与ASCII对照表的整理
- 计算机快速切换任务,电脑多任务窗口切换:除了Alt+Tab,你还知道什么?
- JUC中的原子类总结
- ArcEngine这本书怎么样
- TankGame1.0
- 2022美赛LSTM
- 拦截器和过滤器的执行顺序和区别
- c语言一个整数犯二的程度编程,团体程序设计天梯赛-练习集 L1-017 到底有多二...
- 悟--心智成熟的旅程
- Markdown目录生成
- python的十句名言_让人恍然大悟的十句名言(双语版)
- 社招+校招被技术面试完虐系列之多方位考查点
- C#敏感词汇过滤(不是正则)
- Unity 彩色打印日志信息
- node.js+puppeteer创建定时任务自动登录网站截取图片
热门文章
- Codeforces round 1098
- CentOS 6.9配置网卡IP/网关/DNS命令详细介绍及一些常用网络配置命令(转)
- 第148天:js+rem动态计算font-size的大小,适配各种手机设备
- iOS - 实现语言本地化/国际化
- Html基础知识详解
- Nginx 备战-优化指南
- CCNA学习指南第十一章
- [置顶] NoSQl mongodb数据库 配置篇
- 表示“总结”、“断定”“概括”、“归纳”的词语
- Window平台实时流媒体