原型
当谈到继承时,JavaScript 只有一种结构:对象。
每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(__proto__),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
原型对象
每创建一个函数,该函数会自动带有一个prototype属性,该属性是一个指针,指向了一个对象,我们称之为原型对象。
Prototype显式原型
每一个函数都有一个prototype属性,这个属性指向了一个对象,这个对象有一个constructor属性,该属性指向函数本身。
如上图,SuperType是是一个函数,右侧的方框就是它的原型。
function test(){}
test.prototype.constructor == test // true
__proto__
隐式原型
每一个对象都有这样一个属性,__proto__
这个属性引用了创建这个对象的函数的prototype。即:fn.__proto__ === Fn.prototype。
__proto__ 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用 Object.getPrototypeOf 方法来获取实例对象的原型,然后再来为原型添加方法/属性。
小结一下
- 所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
- 所有函数除了有_proto_属性之外还拥有prototype属性(显式原型)
- 原型对象:每创建一个函数,该函数会自动带有一个prototype属性,该属性是一个指针,指向了一个对象,我们称之为原型对象。
var obj = {}
// 每个对象都有一个__proto__属性,指向创建该对象的函数的prototype
obj.__proto__=== Object.prototype
Object.prototype.__proto__=== null
Object.__proto__=== Function.prototype
Function.__proto__===Function.prototype //true
Function也是一个函数,函数是一种对象,也有__proto__属性。既然是函数,那么它一定是被Function创建。所以——Function是被自身创建的。所以它的__proto__指向了自身的Prototype。
原型链
访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。
上图中,访问f1.b时,f1的基本属性中没有b,于是沿着__proto__找到了Foo.prototype.b。