您现在的位置是:网站首页> 内容页

从我的校长生涯谈原型和原型链

  • 海洋之神线路检测
  • 2019-05-05
  • 278人已阅读
简介简述引用类型关于引用类型的赋值,上篇已经写过。如果说引用类型是地点,我们操作的就是它的地址;如果说引用类型是房子,我们操作的就是它的钥匙;如果说引用类型是人物,我们操作的就是它的手机号

简述引用类型

关于引用类型的赋值,上篇已经写过。

如果说引用类型是地点,我们操作的就是它的地址;

如果说引用类型是房子,我们操作的就是它的钥匙;

如果说引用类型是人物,我们操作的就是它的手机号;

如果说我们不用比喻,我们操作的就是它的引用。

至此,除了赞叹我的排比句是多么荡气回肠之外,你一定也发现:

引用类型就是一种有联系方式的数据类型这种间接关系,使不同变量共享同一数据成为事实

例如

var a = {n: 1}

用变量a保存了{n: 1}的引用,通过这个引用可以操作{n: 1},这个引用就是联系方式。

var b = a

a的引用赋值给b,变量b也保存了{n: 1}的引用,也可以操作{n: 1},这就是共享。

好比,你和你的房间的联系方式,就是房钥匙。

因为你有房钥匙,所以你才能够进房间,操作房间里面的东西。

如果路人甲默默复制一把,路人甲就可以和你一样,能够操作房间里的东西,这就是共享。

问题来了————

你俩虽然有你房间的钥匙,但是你俩拥有这个房间吗?

答案是肯定的。

即使是间接拥有,也是拥有。

好了,明白了上面的东西,原型就不是问题了。

我的校长生涯

在表达我对原型的理解之前,我想先讲一个发生在我身上的不真实的故事。

接下来,我将讲述我的一次创办学校的经历。

阶段一、白手起家

回到多年前。

我是小强,此时我正打算创建一所学校,所以大家也可以叫我小强校长。

首先,我要培养一个老师来替我上课,因为作为一个校长,我还有很多其它事情要做。

很快,我将多年的教学经验传授给一个叫孔仔的人,培养出第一个老师。

后来呢,孔仔也培养出一批又一批的学生。

阶段二、学科多样化

学校算是建成,孔仔也能完成教学任务,不断培养学生。

但是我发现一个问题,一个人的力量毕竟有限,虽然孔仔能完成基本教学,却没有精力在每个学科上做到专精。

这就导致,培养出来的学生没有专长,大多很普通。

终于有一天,我的学校得到许多好心人的赞助,我当时表示力度大点十分感谢。

钱多了,我就可以培养出更多的老师,不同特色的老师又可以培养出不同特色的学生,这不正是我的毕生所追求的东西吗?

于是,我的学校除了孔仔老师,又有了语文老师、数学老师、思想品德老师......

而且我还可以培养更多学科的老师。

阶段三、建设图书室

不知何时开始,有一些老师会找我申请一些教学方法的书,这我是十分支持的,可以说是有求必应。

随着申请的老师越来越多,我总结了一些很多老师会用到的教学方法的书,于是我就想:

不如我在自己办公室旁边建设一个图书室,把这些常用的书放在里面,老师们想看的时候来这里看不就行了。

很快有老师向我反映,他们其实也有相同的困扰,学生也会向他们申请一些课程相关的书,而且经常是相同的。

于是我决定,只要是老师,都要有一个自己的图书室,存放自己学生通常会用到的书或器材。

我也是老师,我是老师的老师。

所以,各科老师的图书室一般都存放各自文化知识方面的教材,而我的办公室存放的是教学经验方面的教材。

马上就要开工了!

可是我又发现,像《小学生必读》这类书,几乎在每个老师的办公室都有,我想:

不如把这类全校学生都读的书,放在同一个地方吧,这样就可以省下更多钱吃喝玩乐建设学校。

我第一想到的,就是孔仔老师,孔仔老师毕竟是我们学校的元老,同时他教的内容是最宽泛的、最不专门的,图书室应该相对空旷,所以就把《小学生必读》这类几乎所有学生都会看的书籍统一放到他的图书室吧。

于是我决定,在给每个老师建造图书室的同时,都建造一条隧道通往孔仔老师的图书室。

我的图书室也是那时候建的,所以我的图书室也有一条通往孔仔老师的隧道。

这样,我培养出来的老师,想看教学经验方面的书籍,就可以到我的图书室。

而我校老师培养出来的学生,想看自己学习方面的书籍,就可以到自己老师的图书室;

如果没有的话,就可以通过自己老师的图书室里的隧道,来到孔仔老师的图书室,看有没有想看的书籍。

这样我的学校就完美了,小强校长还是挺不错的哈?

原型和原型链

先把图放在这里。

javascript的培训方式

在javascript中,Function扮演的就是校长的角色。

首先,他不想亲自去培养学生,所以他培养出了第一个老师孔仔。

Object就相当于孔仔一样可以培养出学生,即通过new Object可以创建对象。

但是,校长为了学生的多样化,又培养了语文老师、数学老师、思想品德老师等老师,而且还可以按需要培养更多老师;

同样,开发者想要创建多样化的数据、符合需要的对象,诸如StringNumberBoolean这些函数对象也必不可少的,而且也可以根据需要写各种构造函数。

可以看到,校长培训出老师,老师再培训出学生;

Function创建函数对象,函数对象再创建对象;

只不过javascript的培训方式是new

javascript的图书室

校长为了避免给每位老师买教学经验方面的书,所以创建了自己的图书室,用来让自己培养的老师共享这些资源;

而我们的Function,也并不想把那些常用的方法都复制一份,保存到ObjectStringArray...以及后来新创建的N多构造函数当中,于是新增一个属性prototype(即原型对象),把一些公共的方法存在里面;

Function让它创建出来的函数对象共享prototype的方式,就是在通过new Function创建函数对象的同时,会使

被创建的函数对象.__proto__ = Function.prototype

比如,在创建Object的时候,会使

Object.__proto__ = Function.prototype

这个场景似曾相识?

没错,这就是我小强校长在创建自己的图书室后,将图书室钥匙送给孔仔老师一把的情景。

此后,孔仔老师就可以来我的图书室,查阅教学经验相关的书籍。

同理,Object也因此可以访问Functionprototype,使用Function为他们精心准备的函数对象的方法。

验证

Object.__proto__ === Function.prototype // true

这里的true表示的就是,钥匙已拿到,Object已拥有Functionprototype

接下来,可能会更多用到“拥有”这个词语

为什么呢?

虽然,根据开篇对引用类型的介绍,可知Object.__proto__ = Function.prototype所做的事情:

无非就是,Function把公共的方法都放在某个房间里,再将钥匙存在自己的属性prototype里;

在赋值时,就是复制了一把prototype里的钥匙,然后存在Object的属性__proto__中。

从这个过程可以看出,原型也不过是引用类型的赋值,就是通过一种联系方式间接拥有某个东西。

本篇文章开始说过,

即使是间接拥有,也是拥有。

首先,对引用类型的及其赋值的理解是必要的。

但是,在理解原型和原型链过程中,可以不必太关注引用类型赋值过程这种细节。

因为原型的目的,就是让实例们都拥有有一个公共区域,方便使用一些常用的方法。

所以类似Object.__proto__ === Function.prototype这种吓人的结构,它要表达的不过就是这个意思:

前者已经拥有了后者提供的公共区域。

就像我的校长生涯那样,当我发现建图书室的作用之后,并不止为自己培养的老师建了图书室。

只要是老师,都要有一个自己的图书室,存放自己学生通常会用到的书或器材

这样,把一些学生的教材也变成共享,就又免得给每个学生都重复买教材。

也就是,不仅Function创建函数对象时,会

被创建的函数对象.__proto__ = Function.prototype

而且函数对象在创建对象时,会

被创建的对象.__proto__ = 创建对象的函数对象.prototype

总结一下,只要new的时候,就会

实例.__proto__ = 创建者.prototype

即只要我创建了你,你就拥有了我的公共区域。

javascript的隧道

回顾我的校长生涯,在我即将开工给我和每位老师建图书室之前,我又想到:

每个老师的图书室里的书,也有很多是重复的,不如把这些重复的都放到元老级教师孔仔的图书室吧。

可是学生只能进各自老师的图书室,怎么让他们也能进孔仔老师的图书室呢?

还记得睿智的小强校长是怎么做的吗:

在建每件图书室的同时,修一条隧道可以到达孔仔老师的图书室,即Function创建对象的同时会

被创建的函数对象.prototype.__proto__ = Object.prototype

例如

Array.prototype.__proto__ === Object.prototype // true

没错,对于javascript来说,Object就是孔仔老师,Objectprototype就是孔仔老师的图书室。

为了减少不同函数对象的prototype的重复,我们把很通用的对象的方法都放到Objectprototype中,并通过上述方法让其它函数都的prototype都拥有它。

这样,每个对象都拥有函数的prototype,每个函数的prototype又都拥有Objectprototype,那么每个对象也都拥有Objectprototype,即对象总能找到早就给它们精心准备好的方法的;

不同原型之间这个不依不饶的关系,就是原型链。

对于学生来讲,他们可以去的办公的总和、以及先后顺序,就相当于我们的原型链。

如图

关于“隧道”的建成,还有一些重要问题:

实际上,被创建的函数对象.prototype.__proto__ = Object.prototype,并非Function做到的,而是Object做到的。

这里,Object其实是使用的这一规则:

只要我创建了你,你就拥有了我的公共区域

因为javascript的创建方式是new,要想实现被创建的函数对象.prototype.__proto__ = Object.prototype,需要先有

被创建的函数对象.prototype = new Object()

即所有对象的prototype都是Object创建的,都是Object的实例。

其它函数对象的prototype因此才能拥有Objectprototype,即实现这种效果

被创建的函数对象.prototype.__proto__ = Object.prototype

那么,如果你是类比我的校长生涯来理解原型的,你就会想:

new在故事中不是“培训”的意思吗,这是不是说,其它的图书室都是孔仔“培训”出来的?

其实,这里我们自圆其说灵活理解就行了,毕竟例子只是用来帮助理解的。

所以,我们的“new”在这时候就是“创建”的意思。

在javascript中,所有对象的prototype都是Object创建的,那么

在我的校长生涯中,故事可能就是这样的:

我的校长生涯后记

这个时刻,学校还只是我(小强校长)和孔仔两个人。

我说,孔仔,为了实现资源的共享,我有一个想法。

孔仔说,啥想法?

我说,把你培养出来后,我已经很累了,但是我们这个学校将来肯定会得到好心人的捐助,也一定会培养更多的老师,老师们也一定需要教学经验方面的学习素材。如果每人我都发一套的话,就有点贵。所以我想给自己建造一个图书室,专门放这些资料,这样不管是你,还是以后培养出来的老师,就都可以在这里共享这些资源了。你觉得怎样,孔仔?

孔仔说,小强校长真抠门英明啊!您看这样如何,每个老师也都建设一个自己的图书室,这样,很多给学生的教材就不用重复买了,他们想用想看的时候去老师的图书室里找就行了,更省钱。

我说,只给学生们开一个图书室不可以吗,每个老师都有图书室会不会浪费?

孔仔说,不太好吧,毕竟不同学科的学生,使用教材的差异还是挺大的,不是很通用,还是建议每个老师都有各自的图书室,方便管理。

我说,有道理,但是总有一些通用的教材,比如《小学生必读》这种,没必要每个老师的图书室里都放一套,不够省钱。

孔仔说,您的意思是?

我说,放你那里吧。

孔仔已经跟不上我的思路,问,其他老师的学生都是去各自老师的图书室啊,这样只有我的学生能看到《小学生必读》这类书吧?

我说,这还不简单,每个老师的图书室都修一条隧道通向你的图书室。

孔仔沉默。

我说,修图书室的事情,就由你来负责吧!先给本校长来一个图书室吧。

孔仔说,不能,我要先给自己修建一个图书室,否则给你修建的时候不知道隧道通向哪里。

我说,好吧。

从此,每当我培养出一个老师,孔仔就帮忙修建一个图书室,同时挖一条隧道通往他自己的图书室。

我们的学校也越来越好。

其它你可能关心的事项

Function.prototype.__proto __ === Object.prototype ?

对。建设每个图书室的时候,孔仔都挖隧道通向自己的办公室了,包括校长的办公室。

Function.prototype.__proto === null ?

对。我们说好把通用资源都放在孔仔办公室,如今已经来到孔仔办公室,还想去哪里?

先有的Function还是先有的Object?

先有的Function。孔仔是我培养出来的,当然是先有的本校长。

先有的Function.prototype还是先有的Object.prototype?

先有的Object.prototype。不然孔仔修建图书室的时候,怎么知道把隧道通向哪里。

constructor是什么?

原型的constructor放的是该原型所属的函数对象,即每个图书室里都放在该图书室所属老师的联系方式,比如电话号码。

小强校长帅吗?

颜值爆表。


如果你有其它关心的事项,可以发表评论或者联系我,或者在这里查看最新更改。

文章评论

Top