要讲清楚JavaScript,首先需要明确以下几个知识点:
Function
也是对象,Function
的prototype
是一个指针,指向一个对象,所以方法的原型Function.prototype
是一个对象。即他们都具有对象共有的特点。对象都具有属性
__proto__
,也称隐式原型。一个对象的隐式原型指向构造该对象的构造函数的原型,这保证了所有实例能够访问在构造函数原型中定义的属性和方法。
总结,方法Function
是一个特殊的对象,除了和其他对象一样有__proto__
的隐式原型,还具有prototype
的显性原型。这个属性是一个指针,指向一个对象,这个对象,我们称作原型对象。原型对象的用途就是包含所有实例共享的属性和方法。原型对象也有一个属性叫做constructor
,这个属性也包含一个指针,指回原来的构造函数。
下面来看一下完整的流程图:
-
构造函数
Foo()
构造函数的原型属性
Foo.prototype
,指向了原型对象,在原型对象里有共有的方法,所有构造函数声明的实例(这里是f1
,f2
)都可以共享这个方法。 -
原型对象
Foo.prototype
原型对象
Foo.prototype
保存着实例共享的方法,有一个指正constructor
指回构造函数。 -
实例
f1
,f2
f1
,f2
是Foo
这个对象的两个实例,这两个对象也有属性__proto__
,指向构造函数的原型对象,这样子,f1
,f2
就可以共享Foo.prototype
上保存的所有方法和属性。
另外,注意构造函数Foo()
除了是方法,同时也是对象,也具有__proto__
属性。那么构造函数Foo()
的__proto__
指向谁?
注意开篇回顾的知识点:对象都具有属性__proto__
,也称隐式原型。一个对象的隐式原型指向构造该对象的构造函数的原型。函数的构造函数的原型对象就是Function
。
因此,构造函数Foo()
的__proto__
指向的正是Function.prototype
。
那么原型对象也是对象,他们的__proto__
具体又指向谁?
构造函数Foo.prototype
指向Object.prototype
;Function.prototype
指向Object.prototype
;Object.prototype
指向null
最后总结一下:
对象有属性
__proto__
,指向该对象的构造函数的原型对象。方法除了有属性
__proto__
,还有属性prototype
,prototype
指向该方法的原型对象。
资料参考:
Doris的回答
https://www.zhihu.com/question/34183746/answer/58068402
《JavaScript Prototype in Plain Language》
http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/