描述:

正如我们所了解,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面向对象——深入理解默认的继承方式原型链相关推荐

  1. JavaScript面向对象——深入理解寄生组合继承

    JavaScript面向对象--深入理解寄生组合继承 之前谈到过组合继承,会有初始化两次实例方法/属性的缺点,接下来我们谈谈为了避免这种缺点的寄生组合继承 寄生组合继承: 思路:组合继承中,构造函数继 ...

  2. 一篇JavaScript技术栈带你了解继承和原型链

    作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...

  3. 深入理解 js 之继承与原型链

    原型链与继承 当谈到继承时,JavaScript 只有一种结构:对象.每个实例对象(object )都有一个私有属性(称之为proto)指向它的原型对象(prototype).该原型对象也有一个自己的 ...

  4. (二)Javascript面向对象编程:构造函数的继承

    Javascript面向对象编程:构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承&q ...

  5. JavaScript原型彻底理解2---继承中的原型链

    一.继承的概念 继承是所有的面向对象的语言最重要的特征之一.大部分的oop语言的都支持两种继承:接口继承和实现继承.比如基于类的编程语言Java,对这两种继承都支持.从接口继承抽象方法 (只有方法签名 ...

  6. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

  7. JS中对象的四种继承方式:class继承、原型链继承、构造函数继承、组合继承(构造函数和原型链继承的结合)

    前言 才发现之前没有对JavaScript中的继承做过总结,不过看得到是不少,接下来就对这几种继承方式做一下总结. class继承 class继承是ES6引入的标准的继承方式. ES6引入了class ...

  8. ES5常用的组合继承及原型链理解

    ES5常用的组合继承及原型链理解 <!DOCTYPE html> <html lang="en"><head><meta charset= ...

  9. 【JS继承】JS继承之原型链继承

    自我介绍:大家好,我是吉帅振的网络日志:微信公众号:吉帅振的网络日志:前端开发工程师,工作4年,去过上海.北京,经历创业公司,进过大厂,现在郑州敲代码. JS继承专栏 1[JS继承]什么是JS继承? ...

最新文章

  1. define##的作用
  2. cvc降噪和主动降噪_降噪蓝牙耳机哪款好?300内建议入手的五款主动降噪蓝牙耳机...
  3. LeetCode 759. 员工空闲时间(排序)
  4. ORA-04063: view DAILY.TMP_TBX_100_0_S4 有错误
  5. 创建react应用程序_如何将React应用程序部署到Netlify
  6. 虚拟键码对照表与ASCII对照表的整理
  7. 计算机快速切换任务,电脑多任务窗口切换:除了Alt+Tab,你还知道什么?
  8. JUC中的原子类总结
  9. ArcEngine这本书怎么样
  10. TankGame1.0
  11. 2022美赛LSTM
  12. 拦截器和过滤器的执行顺序和区别
  13. c语言一个整数犯二的程度编程,团体程序设计天梯赛-练习集 L1-017 到底有多二...
  14. 悟--心智成熟的旅程
  15. Markdown目录生成
  16. python的十句名言_让人恍然大悟的十句名言(双语版)
  17. 社招+校招被技术面试完虐系列之多方位考查点
  18. C#敏感词汇过滤(不是正则)
  19. Unity 彩色打印日志信息
  20. node.js+puppeteer创建定时任务自动登录网站截取图片

热门文章

  1. Codeforces round 1098
  2. CentOS 6.9配置网卡IP/网关/DNS命令详细介绍及一些常用网络配置命令(转)
  3. 第148天:js+rem动态计算font-size的大小,适配各种手机设备
  4. iOS - 实现语言本地化/国际化
  5. Html基础知识详解
  6. Nginx 备战-优化指南
  7. CCNA学习指南第十一章
  8. [置顶] NoSQl mongodb数据库 配置篇
  9. 表示“总结”、“断定”“概括”、“归纳”的词语
  10. Window平台实时流媒体