Javascript 进阶 6-2 原型在哪里?

这篇文章主要是要来介绍原型

http://img2.58codes.com/2024/20121770fHj3BorEHM.png

在介绍原型之前,我们要先来複习物件的内容

http://img2.58codes.com/2024/20121770rNNng1Ersf.png

当我们要定义一只狗的时候,我们会利用物件的资料结构,来对这只狗进行描述。

例如它的颜色、体型大小,以及可以吠叫的方法。

主要的原因就是因为 JS 基本上都是由物件的方法去构成资料。

而原型呢也是一样的概念喔!

在前一篇文章,类别继承中我们有提到,如果我们要定义一个像是这样的内容,我们会使用 class 来定义它。

但是 JS 中都是使用物件来定义,所以我们在定义原型的时候也是使用物件的方式来定义。

http://img2.58codes.com/2024/20121770PxzRansiaA.png

如果狗要透过这个原型来建立实体的话,也是透过继承的方式继承了原型的属性跟方法,因此这就是两个物件的概念。

原型的狗就会有颜色、体型大小,以及可以吠叫的方法。而在实体的狗呢这些属性就会有可以自定义的空间。

那么吠叫的部分就可以继承原本原型的方法。

http://img2.58codes.com/2024/20121770puIpGxnGFX.png

实际上,当我们运行JS的时候,新增一个物件的实体的时候就会有属于该实体的属性

那么原型的部分依样也会有它自己的属性,那这样的结构上依然是属于两个物件。

另外,除了实体可以继承一个原型之外,原型也可以继承另外一个原型喔!

那么在另外一个原型的部分也可以拥有自己的属性以及方法,那么这样的继承关係可以一段一段的向上继承,这样的继承状态我们又称为原型链。

再来,这个实体我们要取用其中的属性的时候,会使用点运算子的方法进行取用,例如 obj.Prop1obj.Prop2

而当我们要取用的属性或是方法没有在这个实体上的时候,就会透过原型链向上查找,直到找到这个原型链的顶端为止。

http://img2.58codes.com/2024/20121770BInTODyBVU.png

除此之外呢,原型还有另一个特色,就是

如果用同一个原型新增了两个实体,这两个实体就会共用同一个原型继承,共用相同的属性名称以及相同的方法。

http://img2.58codes.com/2024/20121770hLjVEZdD0P.png

接下来总结一下观念:

http://img2.58codes.com/2024/20121770a3QGohidQC.png

那么我们再来就透过程式码的运作来进行刚刚上面的观念验证吧!

var a = [1, 2, 3];console.log(a);

执行之后我们把这个阵列打开来看

http://img2.58codes.com/2024/20121770IcwIW3UsIS.png

可以看到里面有对应 0 1 2的属性,因为我们知道阵列的本质其实也是物件,所以这里的 0 1 2其实也是这个阵列的物件属性。当然 length 也是。

所以物件的属性的话我们有两种取值的方式,一个是 [] 一个是 .

http://img2.58codes.com/2024/20121770rrMkfctgOo.png

那么这个阵列现在是属于一个实体,我们可以透过 proto 的属性 来看看它阵列的原型

http://img2.58codes.com/2024/20121770fOGQaKn1dw.png

可以看到阵列的原型中有许多的方法,那么我们刚刚也提到可以透过点运算子取用他的方法。

那么这边我们选用的是 forEach 的方法,透过这个方法可以将阵列的每个值都遍历过一遍。

http://img2.58codes.com/2024/20121770JcyCBtCoUg.png

那么这个 forEach 就不是属于 a 这个实体的方法,而是属于阵列原型的属性方法。

还有我们刚刚也有讲到原型是共用的,所以我们再来新增 b 这个新的阵列 为 [4, 5 , 6]

我们刚刚也有提到 proto 的属性是指向阵列的原型,所以我们照理说也可以用 proto 的属性新增方法到阵列的原型上,让 b 阵列也可以取用到相同的方法。

PS: proto 的属性虽然可以达成一样的效果,但一般我们还是不建议这样使用,后面的章节会教大家使用 prototype 的属性将要新增的 function 挂载到原型上,让其他实体也可以取用到。

那么这边我们把阵列最后一个值取出来的方法透过 proto 的属性挂载到阵列的原型上。

http://img2.58codes.com/2024/20121770E7szaPA7p8.png

http://img2.58codes.com/2024/20121770789NXfNtlR.png

另外我们就真的实用这个 getLast 的方法看是否有成功

http://img2.58codes.com/2024/20121770DMqSlsreM4.png

很明显就成功的印出我们想要的内容。

讨论一下原型的层级问题吧!

我们刚刚说到,打开a 或 b 的 proto 的属性能够找到阵列的原型。

那么继续往下找又可以找到另一个 proto 的属性,再把它打开以后会看到的是物件的原型。

因此这个阵列的原型其实是继承了物件的原型。

而继续往下看就可以看到物件的一些方法,但到最底就没有 proto 的属性,代表说这个物件的原型就是原型链的最顶层了!

好,我们再来看一些code。

http://img2.58codes.com/2024/20121770SiNkPYAm9x.png

我们新增了一个新的物件,并且对该物件的物件原型上挂载 getName 的方法,而之后打开 a 跟 b 的原型链最顶端的物件原型,也可以找到 getName 的方法的方法喔!

http://img2.58codes.com/2024/20121770ER7qvIdIjg.png

那么接下来我们就试着在阵列中使用这个 getName 的方法。

首先我们先对 b 这个阵列加入了 name 的属性,之后我们预期用 getName 应该可以抓到我们刚刚设定的 name 的内容

http://img2.58codes.com/2024/201217703VzUTQBrj9.png

果不其然成功了,但阵列上并没有 getName 的方法,所以透过向上查找的方式,在物件的原型上找到了 getName 的方法并且使用它。

那么这篇文章就介绍了原型以及原型链的概念以及实作。

如果没有问题的话就继续往下巴~!汪汪


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章