原型链类型的题在面试中属于高频考点,下面用一个经典的面试题还原js中原型链的真面目。javascript
请问:f有方法a和方法b吗?java
var F = function () {}; Object.prototype.a = function () {}; Function.prototype.b = function () {} ; var f = new F()
在作这题以前,必定要了解js中原型链的一些继承关系,把那种继承关系图记在脑子里,而后看到题目后把各自一一对应寻找继承关系,以前走过弯路,初学js时在网上找原型链的图,又复杂又记不住,相似这种:
不要看了,反正我是看不下去。面试
在js中,对象都有__proto__属性,通常这个是被称为隐式原型,该隐式原型指向构造该对象的构造函数的原型。
函数比较特殊,它除了和其余对象同样有__proto__属性,还有本身特有的属性----prototype,这个属性是一个指针,指向一个包含全部实例共享的属性和方法的对象,称之为原型对象。原型对象也有一个constructor属性,该属性指回该函数。segmentfault
按照上述的理论能够把构造函数(函数)、对象(构造函数new出来的)、Object(顶层的对象)之间的大概关系串起来。相似以下:函数
这张图是我在吴华的javascript高级进阶课程中看到的截图,受用至今。
记住这四个最主要的点就ok了,对照上图理解记忆:spa
隐式原型
(__proto__
),它指向构造函数的原型对象(prototype
)。隐式原型
(__proto__
)它指向Object
的原型对象(prototype
).Object
的原型对象有个constructor
指向Object
自己。constructor
指向构造函数自己。这里看完你就能明白对象上的toString()
或者valueof()
是怎么来的了,打印一下Object
的原型对象,就能获得结果,你去访问对象的属性(包括方法),他会先找自身有没有这个属性,没有的话会沿着原型链一层一层往上找,例如上图,我要访问obj
的showAge
方法,他自己有,返回他自己的showAge
方法,要访问showUserName
,obj
没有,会沿着隐式原型去看看构造函数的原型对象有没有,有的话返回,没有的话继续去Object
的原型对象去找,依次往上。这也不难理解为何对象上都有toString()
方法了。prototype
理解原型链后,再回到最初的那道面试题:指针
在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数。构造函数首字母通常大写
那我理解的是理论上任何一个函数均可以当成一个构造函数。
其实上面的原型图还有一部分Function
的没画出来。
了解这个以前,带着另外一个面试题去思考:
原型链顶层是什么?按照上面的图你可能会认为是Object
或者Object.prototype
,其实不是。
注意:code
要理解原型链顶层要和原型链其余地方的理解有一些不一样,这里Object和Function及其原型要分开看,不能将原型和自己看做是理所固然的关系