欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

js中关于原型链与继承的理解

程序员文章站 2022-04-25 16:03:31
...
js中的原型链是比较难理解的一部分知识,而继承又是依赖于原型链,所以原型链是我们必须去掌握的。在学习原型链之前,我们需要去介绍一下原型。建议这部分重在理解,不推荐死记硬背。

1、原型

js中只有函数对象才有原型,原型也是个对象。例如,我们创建一个save函数,通过typeof来查看其类型,返回值是”object”,说明其实一个对象。
js中关于原型链与继承的理解
图1 函数对象
那么,函数的原型包含哪些内容呢?通过打印输出,我们可以看到,其原型包含两部分,一是constructor,二是proto。我们首先了解下constructor,后文会介绍proto
js中关于原型链与继承的理解
图2 函数对象的原型
学过java的都知道constructor是构造器的意思,其包含有关构造器的一些信息,比如参数、调用者等。
前面说过只有函数对象才有原型,那么普通对象有没有呢?下面通过实例验证,通过save构造出一个对象fileSave。
js中关于原型链与继承的理解
图3 普通对象
从上面的例子看出,普通对象是没有原型的,但是其有proto属性。
小结:从以上分析,我们学到函数对象有原型属性,普通对象没有原型属性。

2、原型链

原型链的实现是依赖proto属性的,其可以理解为C语言中的指针,java中的引用。在js中,proto指向的是什么呢?还是抛出实例,下面通过打印输出fileSave的proto属性:
js中关于原型链与继承的理解
图4 对象的proto
你是不是有所发现,fileSave的proto值和图2中的save函数对象的prototype一样,即proto指向save的原型。我们知道fileSave对象是通过new save();创建的,故我们得出结论fileSave的proto指向其构造函数对象的原型。为了验证结果,我们再次通过save创建一个对象imageSave,看一下它的proto属性值。
js中关于原型链与继承的理解
我们再次发现,imageSave的proto指向了save的原型。因此,我们可以知道对象的proto指向其构造函数的原型。那么,save也是一个对象,它的prto应该指向它的构造函数的原型,即Function的原型。
js中关于原型链与继承的理解
另外,我们从第一节知道原型也是对象,其proto属性的指向又是如何呢?以实例说话,下面打印出save.prototype.proto值。
js中关于原型链与继承的理解
图5 save.prototype.proto
从图5知,save.prototype.proto的值是Object的原型。我们很好奇,Obejct.prototype 的proto的值,打印出来看看。
js中关于原型链与继承的理解
是null,可以理解,毕竟其实最顶层的对象啦。
从上面的分析得出下面的链图:
js中关于原型链与继承的理解
图6 原型链
小结:通过这一节的分析,我们学到原型链的实现是依靠对象的proto属性。如果通过函数对象创建一个对象,那么该对象的proto属性就指向其构造函数的原型。
3、继承
在讲继承之前,我们先来学习下属性的查找。在js中,其会按照原型链去查找属性,如果自己没有,就根据proto属性依次往上找。下面我们,先写一段实例代码。

save.fileName = "oo"save.prototype.fileName = "lili";fileSave.fileName = "haha";

js中关于原型链与继承的理解
这时我们如果打印fileSave.fileName的值,很明显得到的是“haha”。但是如果我把fileSave.fileName = “haha”;去掉,再次打印会输出什么呢?
js中关于原型链与继承的理解
从打印结果,我们知道会根据proto属性中去找fileName属性,即根据图5的链图去查询需要的属性。在这里,如果没有save.prototype.fileName = “lili”;这段赋值代码,打印出来的就是undefined,因为原型链中没有对应的属性。有人可能会说,为啥不会输出“oo”,的确从代码中看到save.fileName = “oo”这段赋值代码,但是我们需要知道save是个函数对象,当执行这段代码时,finName会在constructor下,并不在原型中,类似于java中的静态属性(在这里不能通过实例对象访问)。
记住:通过普通对象调用属性,该查找只会在prototype的属性中查找,并不会在constructor中查找。如果在save的原型中没有找到,又会到save.proto中查找,依次进行下去。
如果知道属性查找方式,那么实现继承就很简单了。例如我们创建一个空对象saveDisk,如果我想访问save中的fileName,我们只需要把saveDisk的proto的值等于save的原型即可(简单理解为把两条不相干的铁链接在一起)。

saveDisk._proto_ = save.prototype

js中关于原型链与继承的理解

以上就是js中关于原型链与继承的理解的详细内容,更多请关注其它相关文章!