原型与原型链
前言
JavaScript 原型与原型链虽然是一个老生常谈的话题,但依然困惑着很多人,今天我再来从另一个角度谈谈这个问题。
两个疑问
先看这样一段代码:
运行一下上面的代码,输出结果为 gogo
。
针对这个结果,有以下疑问:
obj 哪来的
__proto__
属性?为什么添加到
__proto__
上的属性,可以直接通过 obj 拿到?
第一个问题
js 中每个对象都有一个“原型”,原型一般可以通过 __proto__
访问到:
可以这么理解:原型,也是一个对象。
就像:
每个“人”都有一个“爸爸”;
但“爸爸”也是一个“人”;
“爸爸”除了是某个人的爸爸外,与其他人并没有本质的区别;
爸爸,也是普通人。
类似的:
“原型”是一个普通的对象;
爸爸也有他的爸爸,原型也有它的原型。
第二个问题
对象与人不同的是:
人不可以随便拿爸爸的东西
而对象可以随便拿原型里的东西
比如,当你向一个对象,索要一个属性时:
如果这个对象没有你要的属性,它就会让它的原型(爸爸)给你
如果它爸也没有,那它爸就会找它爸的爸
比如下面这个例子:
因为 obj 本身没有 haha 这个属性,所以它会去自己的 __proto__
中查找,如果还没有找到,那就会向它的 __proto__.__proto__
中去找,直到找到 haha 属性或者 __proto__
链返回 null 为止。
再换一种写法:
查找 haha 属性的过程是: obj -> 爸爸 -> 爷爷
,像不像是一条链子呢?这就是原型链。
关于 prototype
有这样一句话:
类是对象的模板
你与我,都是人,“人”是类,是模板。
你与我,都属于“人”类,有很多共性:
有一张嘴
有两条腿
会吃饭
会睡觉……
这些共性是人类共有的。
当然,你与我做为独立的对象,肯定也存在差异,比如:我的名字叫 X,你的名字叫 Y 。这些不同点,是对象“私有”的。
看一段 js 创建对象的代码(注意注释部分):
类比于人类社会,就是:
你的兄弟姐妹和你“共享”一个爸爸
当你的爸爸烫了个头时,你弟弟的爸爸也烫头。这个过程中,不是两个爸爸同时烫头,而是本来就一个爸爸。
重要结论:
实例化的过程中(也就是“当 new 一个对象的时候”),类的 prototype 成为对象的原型
同一个类的多个实例(也就是“对象”),共享一个原型
结束语
原型是 js 底层的东西,不懂原型,几乎不影响工作。
类似“原型有什么用”的问题,就像“砖块(或水泥)对盖楼有什么用”。其实在写代码的过程中,几乎不会用到原型的知识。但是如果遇到了问题、出现了 bug、性能优化时,底层的知识是肯定有大用途的。
~
~ 本文完,感谢阅读!
~
评论