js 的原型链第一反应是prototype,但是不一定能反应到__proto__这个属性。
而事实上,原型链是__proto__串起来的,而不是prototype。
prototype只能说是在构建这个原型链的机制中起到关键作用。
一,常见类的原型链
下图的原型链图中,箭头代表__proto__属性。
以String为例,String的原型链为:
String->Function.prototype->Object.prototype->null
每一个箭头都是一个__proto__属性。而最后结尾是null。
这个null的作用是带来链的终结,同时记住这是null,不是undefined。
我们可以看到原型链的起点是一个对象,这个对象可以是任何对象或者函数
(js里面对象和函数的差别太微妙了)
> function f1(){}
> undefined
> f1 instanceof Object
> true
> typeof f1
> "function"
这个原型链的终点是null,而原型链的中间节点全部是XXX.prototype.这就是prototype在构建原型链时所起到的关键角色。
二,实例化对象的原型链
这是你可能要问了String.prototype到哪去了,String的原型链难道和String.prototype没什么关系吗?是的。
var str=new String('123')
事实上String.prototype是为String所实例化的对象提供原型链的,执行这条命令之后,str的原型链是什么样的:
str->String.prototype->Object.prototype->null
为什么如此,我们先看str->String.prototype,
这是因为当我们执行var str=new String('123')时,js自动将str的__proto__赋值为String.prototype。于是形成这样的链。
再看为什么String.prototype->Object->prototype。
这个我们可以想像。String.prototype的实现一定是这样的:
String.prototype=new Object();//###
String.prototype.indexOf=function(){};
String.prototype.substr=function(){};
...
根据刚才的经验,执行###这一行时,js也是自动把String.prototype的__proto__赋值为Object.prototype.所以有了这一个链。
链图如下:
三,instanceof的实现原理
现在来看一个操作符的实现原理,
A instanceof B
加入有上面这条语句,那么背后的判断过程是:
1.从下往上遍历A的原型链。
2.如果链上的某个节点等于B.prototype,则返回true。
3.否则继续向上取原型链节点。
根据这个规则,我们可以推断:
//由第一个图可以看出:
String instanceof Function; //true
String instanceof Object; //true
//从第二个图可以看出
var str=new String('123');
str instanceof String; //true
str instanceof Object; //true
str instanceof Function; //false
byebye