前言
这篇其实拖了相当久了。是因为自己很长时间对于原型和原型链的概念不是很清楚。现在已经大抵弄明白了。那么今天来总结一下吧~
一个题目
在总结之前,先放上一道我纠结了很久很久的题目,是在看别人的面试经历里面看到的。下面评论说考察了原型链的知识。经过百度。。发现这道题答案还有不同的声音。遂开始了我的弄懂原型链的历程。
var F=function(){
};
Object.prototype.a=function(){
};
Function.prototype.b=function(){
};
var f=new F();
f能拿到a和b吗?
先公布答案吧~能拿到a不能拿到b,如果我们在浏览器中进行审查的话,会发现报错b未定义。
那么为什么呢?我们先直接来做出解释吧:
拿属性的时候,JS中是通过原型链一层一层向上遍历去拿的。
F的原型链 F→Function.prototype→Object.prototype→null;
f的原型链 f→F.prototype→Object.prototyoe→null;
通过原型链我们可以看到F既可以拿到a也可以拿到b,而f却只能拿到a,不能拿到b。
那么什么是原型链,什么是原型,其中又有什么容易让人混淆导致网上答案有不一样呢?
原型和原型链的解析
原型:在JS中,每当定义一个对象(函数)的时候,对象中都会包含一个预定义的属性。其中函数对象的一个属性就是原型对象prototype。(普通对象没有prototype属性!!普通对象没有prototype属性!!!但是有proto属性)
(那么什么是普通对象,什么是函数对象呢?
function f1(){};var f2=function(){};var f3=new Function(‘str’,’console.log(str))。类似这种函数的创建,是函数对象。
而 var o1={};var o2=new Object();var o3=new f1();这种形式的赋值,是普通对象。)
原型对象就是普通对象。当我们console.log(o1.prototype)的时候,会返回o1{},而它的类型是Object;全局变量Object的prototype也是Object。
但是也有特例,Function.prototype的类型是Function。而且Function.prototype不存在prototype属性
JS中所有的函数包括Funciton和Object的原型都是Function.prototype。
其实原型的概念不是那么冗长,它的作用就是用来进行继承。提到继承就得讲到原型链的概念了。
原型链:
在属性查找时,也就是刚才题目中提到的拿,JS在进行属性超找时,会从自身开始查找,然后一层一层向上遍历,通过proto来查看原型中是否存在查找的属性,如果没有就继续查看其原型的protol中有无查找的属性。知道Object.prototype→Null。
还需注意的是,在JS的原型对象(prototype)中,还包含有一个constructor属性,这个属性对应创建所有指向该原型的构造函数。
函数对象的原型prototype和其构造函数,通过constructor和prototype属性实现相互的引用。
那么我们可以做一下总结:
1.首先所有的对象都有protol属性,这个属性指向的是对应对象的原型。
2.所有的函数对象对象都具有prototype属性,该属性的值会被赋值给该函数创建的对象的protol属性
3.所有的原型对象都有constructor属性,该属性对应创建所有指向该原型的实力的构造函数。
4.函数对象和原型对象通过prototype和constructor属性进行相互关联。
一经典的图解
这里贴出一非常经典的图片~非常方便理解!
结语
原型和原型链的问题牵扯到非常多的知识,栈和堆、作用域、上下文等等等。那么接下来一定会把这些基础知识都弄明白。下一篇会把自己学习canvas画的时钟整理成笔记!^ - ^