美文网首页饥人谷技术博客
原型与原型链的意识流探讨

原型与原型链的意识流探讨

作者: 许骁Charles | 来源:发表于2019-03-27 02:13 被阅读13次

写这篇文章的时候,我还没有开始系统学习JavaScript的OOP(面向对象编程),甚至有关函数这个一等公民都还没写一篇像样的博客。这里就浅谈一下对__proto__prototype以及constructor之间那些爱恨情仇的意识流理解。

先看一段代码:

function Foo(){}
var f1 = new Foo()
var o1 = new Object()

这段代码运行的时候,js的世界里发生了什么?

首先,如上图所示的左边,声明了Foo类型和Object类型的两个对象f1和o1。他们也会有同样是Foo类型和Object类型的其他兄弟姐妹,比如f2,f3……fn,o2,o3……on,他们各自有各自的方法属性,都旗帜鲜明,但如果有一些共同的特点,那么是不是每new一个兄弟出来,这些共同点又要写一遍?

不可能,程序员都很懒,抢票都要写脚本自动去刷。

这些公共的属性方法,显然应该放到一个地方集中定义,这就是prototype的主要作用:定义共享的属性和方法。存放这些公共属性方法的对象就被称为原型对象。如图就是函数Foo()的原型对象就是Foo.prototype
而因为原型对象的属性和方法,并不属于实例对象本身,而是无私地施舍给这些家伙用的,因此,只要修改原型对象,这些变动会立刻体现在所有实例对象上。所谓“牵一发而动全身”正视如此。

那么这些实例对象又如何访问到原型对象里的属性和方法呢?答案是每一个对象在诞生之初就有的__proto__属性。通过__proto__属性,每个儿子都有得以窥探他们爸爸那些小九九的钥匙。

这时候,Foo.prototype这个原型对象也想找爸爸了,于是它也掏出自己的钥匙__proto__去打开了它爹的门,见到了亲爹Object.prototypeObject.prototype也不甘示弱,想掏出了钥匙__proto__,然而,已经没有门给它开了,钥匙上分明写着“你是他们的祖宗,你找**呢”,Object.prototype.__proto__ === null

上面这个“找爸爸”的过程实际上就是js在原型链上给这些子子孙孙们找原型对象的过程。这些对象之间通过__proto__一层层联系起来,形成了像链条一样的东西,就是原型链
如果实例对象没有某个属性或方法,js会顺着原型链一直往上找,直到祖宗Object.prototype,如果还没有,就返回undefined。就像你问爸爸,为什么我没钱?你爸爸问爷爷……一直问到十八辈祖宗,他托梦说,吾辈向来家徒四壁,基因上你就别指望有这个属性了,只能通过自己的努力去添加挣钱的方法。
另外,如果你和你爸爸有一个相同的方法,比如“出门方式”,你爸开大奔,你骑摩拜,这就是对象对其原型的同名属性或者方法的覆盖(overriding)

那么constructor又是什么呢?
翻译一下,构造器,而所有构造器都放在函数一列,故为构造函数constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。

在上图中,Foo.prototype中的constructor属性指向了函数Foo,而Foo.prototype中的所有属性方法是要被函数Foonew出来的实例对象继承的,因此每个实例对象都有了constructor属性,指向了函数Foo,以此表明,这些实例是由函数Foo构造出来的,即f1.constructor === Foo

另一方面,有了constructor属性,就可以从一个实例对象新建另一个实例。比如var f2 = new f1.constructor()

constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。

上图转换为代码,可以得到如下的等式:

f1.__proto__ === Foo.prototype
Foo.prototype.constructor === Foo
Foo.__proto__ === Function.prototype    // Foo是Function构造出来的实例
f1.__proto__.__proto__ === Object.prototype

Function.__proto__ === Function.prototype   // 一切函数都是由函数Function构造的,包括他本身
Function.prototype.constructor === Function
Function.constructor === Function  

Object.__proto__ === Function.prototype  // 函数Object也是由Function构造的
Function.prototype.__proto__ === Object.prototype 

记住一个永恒的公式:对象.__proto__ === 对象的构造函数.prototype
而所有函数都是由 Function 构造出来的,所以

Number.__proto__ = Function.prototype // 因为 Number 是函数,是 Function 的实例
Object.__proto__ = Function.prototype // 因为 Object 是函数,是 Function 的实例
Function.__proto__ == Function.prototye // 因为 Function 是函数,是 Function 的实例!

总结:
以上是我对原型和原型的浅薄理解,等我深入学习了JavaScript的面向对象编程,梳理顺了this的相关知识,相信会对原型和原型链有更加深刻的认识。

相关文章

  • 原型与原型链的意识流探讨

    写这篇文章的时候,我还没有开始系统学习JavaScript的OOP(面向对象编程),甚至有关函数这个一等公民都还没...

  • JavaScript 原型、原型链与原型继承

    原型,原型链与原型继承 用自己的方式理解原型,原型链和原型继承 javascript——原型与原型链 JavaSc...

  • 2019-01-28

    原型与原型链

  • 廖雪峰JS小记

    (function(){})() 原型,原型链 浅谈Js原型的理解JS 原型与原型链终极详解 对象 对象:一种无序...

  • Javascript(三)之原型继承理解

    进阶路线 3 原型继承 3.1 优秀文章 最详尽的 JS 原型与原型链终极详解 一 最详尽的 JS 原型与原型链终...

  • js实现继承的几种方式

    js实现继承有几种方式,这里我们主要探讨 原型链继承 构造继承 组合继承(原型链和构造继承组合到一块,使用原型链实...

  • JavaScript 面向对象第一篇

    1.原型链 ---- (实例对象与原型之间的连接 叫做原型链) 2. hasOwnproperty ----(看是...

  • 原型与原型链以及继承

    今天复习下原型与原型链的知识,以及记录新学的继承知识点。 知识点纲要 原型与原型链 es5与es6继承 什么是原型...

  • JavaScript深入理解this关键字(一)

    摘要 最近在公司需要做培训,我打算把JavaScript中的原型与原型链讲给大家。但我在梳理原型与原型链的时候发现...

  • js_继承及原型链等(四)

    js_继承及原型链等(三) 1. 继承 依赖于原型链来完成的继承 发生在对象与对象之间 原型链,如下: ==原型链...

网友评论

    本文标题:原型与原型链的意识流探讨

    本文链接:https://www.haomeiwen.com/subject/tklyvqtx.html