javascript是一种基于原型的语言,它的继承是靠一个中间对象-----原型对象来完成的,通过原型对象
形成一个属性的查找链,即所说的原型链。为了实现代码的重用,我们有必要把那些需要共享的属性和方法
集中起来,在传统的面向对象的语言中这个任务由类完成,而在javascript中没有类的概念,而是依靠原型对
象来把这些公用的属性和方法集中起来形成一个共享的对象,当需要共享这个对象时,只需要为对象添加一
个指向该原型对象的指针即可。通常这个指针在javascript的引擎实现中为__proto__。任何对象都可以成为
一个原型对象,包括普通对象。一旦__proto__指向了这个对像,那么他就可以访问到该对象的所有的属性
和方法。
javascript本身为我们提供了大量的原型对象,总结一下主要有以下几种:
- Array.prototype(为所有数组对象提供方法和属性)
- Object.prototype(为所有对象提供属性和方法)
- Function.prototype(为所有函数对象提供属性和方法)
- String.prototype(为所有字符串对象提供属性和方法)
- Boolean.prototype(为所有布尔对象提供属性和方法)
- RegExp.prototype(为所有正则表达式对象提供属性和方法)
- Number.prototype(为所有数值对象提供属性和方法)
- Date.prototype(为所有日期对象提供属性和方法)
在这些原型对象中,Object.prototype是一个比较特殊的对象,其他原型对象都有一个指向Object.prototype
的指针,所以数组、函数等一切对象才拥有了必要的toString、constructor等属性.,也可以说这个原型对象的可用
属性和方法最少。而这个对象本身拥有一个指向空对象的指针,也就是说原型链到此结束。另外一个较为特殊的对
象是Function.prototype,他包含了所有函数对象应该拥有的属性和方法,也就是说,包括Function本身在内的所有
函数都有一个指向Function.prototype的指针,因此拥有了函数方法和属性。
但是我们一般不会直接这样做,在javascript中,一般用于保存原型对象的是函数,或者说只有函数对象
才拥有原型对象。比如Object拥有Object.prototype,Function拥有Function.prototype。我们自定义的函数也
拥有一个原型对象,但通常这个原型对象是一个空对象,我们可以向其中添加属性和方法。
为了彻底理解__proto__和prototype的区别,最显然的方法是研究javascript内置对象Function。首先Function
是一个函数,他拥有一个原型对象,这个原型对象为所有函数实例包括Function自己提供了一个原型对象——
Function.prototype。同时我们知道,Function也是一个对象,因为Function本身是Function的一个实例,那么
Function.__proto__===Function.prototype。Function.prototype是一个对象,他有一个__proto__属性指向
Object.prototype,那么自然而然Function.__proto__也有一个属性__proto__,且指向Object.prototype,注意这
个__proto__是Function.prototype而非Function的属性。所以说Function实例都会拥有Object.prototype中的属性
就一目了然了,如果你能看到这个关系后就马上明白,那么对原型的概念基本也就掌握了。
总的来说,Function同时拥有__proto__和prototype两个属性,而特殊的是Function.__proto__===Function.prototype。
所以有时会在这点困惑。一个等式Object.prototype===Function.__proto__.__proto__&&Function.__proto__.__proto__
===Function.prototype.__proto__