JavaScript原型链的学习总结

关于原型链的学习总是很迷,看了过段时间就忘,或者不理解,看多了就走火入魔了

这次换个思路来学习,先搞懂JavaScript中的Object和Function的关系、源头

(假设你已经看了很多关于原型链的文章和各种眼花缭乱的图...)

1.Object

首先打印下Object,可以看到Object是个function Ojbect(){...},打印它的内部结构里面有很多属性,其中有个prototype(原型),后面有用

新建一个对象let a={},其实就是let a=new Object(),普通对象a就是构造函数Object的实例化

打印一下a的内部结构,可以看到a内部有个__proto__属性,里面有构造方法和toString等方法

我再打印下Object.prototype,发现和a里面的__proto__长得一样,那是不是一样呢,试一下

发现果然一样,也就是说a的__proto__指向了函数Object的prototype

再新建一个let b={},试试看a和b的__proto是否相等

 

发现也是相等,也就是a和b的__proto__都指向函数Object的prototype,在内存中是同一块空间

为什么这么做呢,试想如果没有这个功能,a和b如果想用toString方法,需要a b分别.toString=function(){...},分别在内存中开辟一块空间,打个比方,内存分成100份且只有100份,每个对象的toString方法占1份,100个就占完了内存,所以JS作者把对象需要共享的属性和方法,放到一个内存空间里,每一个对象都有一个属性都指向这个空间,节省资源。

那么Object的prototype指向谁呢,试一下

是null,这个不太好理解,可以理解为到此为止了,不要继续往上找了,万物起源皆有源头,就到这吧。

总结下,就是普通对象的__proto__指向Object.prototype,我们只是通过控制台打印去佐证了这一点,先记住吧,js作者是这么设计的,就像1+1=2。

第一条结论:普通对象最终继承自Object.prototype,Object.prototype直接继承自根源对象null

2.Function

我们需要去搞懂Object和Function的关系,在这之前先记住

(1)只有函数对象有prototype,就像上面的Object里有prototype和__proto__,而普通对象a中没有prototype,只有__proto__

(2)prototype里存储的是原型,留着继承给下一级的,而下一级的__proto__指向上一级的prototype,自身的prototype和__proto__是没有关系的,当然除了Function的,后面讲

打印Function,发现Function.prototype.__proto__和Object.prototype长得也一样,一打印果然是true,也指向Object.prototype

得出第二条结论 Function.prototype继承自Object.prototype

马上进入最绕的部分

Object是函数,它的__proto__指向上一级的原型,也就是Function.prototype,Object继承自Function.prototype,这很好理解

Function继承自谁,它的上一级是谁,Function的__proto__指向谁,答案是Function.prototype,Function自己的原型...这就有点无解了,你要问为什么,只能问JS作者了

打印出来可以看到里面是常见的apply call bind等方法

结合上面得出的第二条结论 Function.prototype继承自Object.prototype

得出第三条结论

一切函数对象都继承自Function.prototype,Function.prototype继承自Object.prototype

像Object、Array和Function本身都继承自Function.prototype,那Function是大王了吗,结果Function.prototype又继承自Object.prototype,这属实是互相继承...最绕的就是这一块了。

----------------------------------------------------------------------------------------------------------------------------

3.分析眼花缭乱的原型图

现在再去看这张很常见的眼花缭乱的图中的红框部分就好理解了

1.Object和Function,这两个谁是大王谁是小王?

2.Object是函数,__proto__指向它的上一级Function.prototype

3.Function也是函数,__proto__指向它自身Function.prototype,可以说Function就是函数中的大王,任何构造函数都是Function的实例

4.Function.prototype.__proto__指向Obect.prototype,所以任何对象,不论是普通对象还是函数对象都是Object的实例

5.Object.prototype.__proto__最终指向null

6.同一个对象的__proto__属性和prototype属性是没有关联的,除了Function。prototype对自身是不可见的,它的作用是留着继承给后代,而__proto__的作用是引用上一级的 prototype 对象

7.我认为Object.prototype就像一个辅助,它的原型中提供一些普通对象要用到的方法,如toString,valueOf,hasOwnProperty等,它的指针指向null,另外它的存在还使得Function.prototype可以指向它,以及所有的prototype通过原型链都指向它,最终指向null,而Function更偏向于实战,在js世界中发挥巨大作用,从它演化出Function Object Array Number String等,再去衍生js中的万物,不好说谁是大小王。

至于上面那个图中其他的知识点,比较好理解了

let o1,o2=new Object(),普通对象o1 o2的__proto__指向Object.prototype

function Foo(),let f1,f2=new Foo(),f1,f2的__proto__指向Foo.prototype,这里Foo.prototype是普通对象,结合第一条结论,普通对象指向Object.prototype,最终指向null

Foo.__proto__指向父级函数Function.prototype,再结合第三条结论,指向Object.prototype,最终指向null

Foo的原型链不同于f1 f2,这里容易混淆,需要分清楚,但是最终殊途同归...

所以什么是原型链,当实例要访问某一个属性时,首先在实例自身查找,如果没有找到,则继续沿着__proto__对象查找,如果还是没找到,则继续对__proto__的__proto__对象查找,如果找到最终__proto__对象为null时都没找到,就返回属性未找到的错误,如果找到了则返回该属性值。而这个由若干个__proto__对象串联起来的查找路径,就称为原型链。

还有一个知识点就是原型的构造函数指向,原型中的构造函数指向函数本身

实例化一个Person叫p,p的构造函数也指向这个函数本身

 

所以,其实可以理解成原型上的构造函数也是Person的一个实例化

同理Object的prototype上的构造函数指向Object

Function的prototype上的构造函数指向Function

再来一张图,如果能看懂,就差不多了

在这里插入图片描述

思考题:

Object.prototype.toString和Object.toString是一回事吗?
答案是:不是。 因为Object.toString是Object.__proto__.toString,也就是去上一级的原型中拿的方法,是Function.prototype.toString,和Object.prototype.toString根本不是同一个函数。

最后,说一下__proto__这个属性,是隐示属性,在有的浏览器中它不是__proto__而是[[Prototype]],具体可以去了解下区别,下面截图是IE的Edge浏览器

关于instanceof

instanceof想必都知道,常用于判断xx是不是xxx的实例,xxx在不在xx的原型链上的,但是基本数据类型,Boolean String Number,直接赋值,虽然proto指向了Boolean的prototype,但是用instanceof却是false,下一篇学习instanceof补充这一块知识

已补充

JavaScript实现一个instanceofhttps://blog.csdn.net/IronKee/article/details/120292452

----暂时到这----

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值