本文已参与「新人创作礼」活动,一起开启掘金创作之路。详情
原型及原型链
这是本人珍藏的图,关系一目了然。
概念
-
显示原型
prototype:函数/方法拥有一个prototype属性,指向函数的原型对象。(通过
Function.prototype.bind方法构建的函数没有prototype属性) -
隐式原型
__proto__:任意对象都有一个内置属性[[prototype]],大多浏览器支持通过__proto__来访问,在ES5中有了对这个内置属性的标准Get方法:Object.getPrototypeOf()(
Object.prototype这个对象是个例外,它的__proto__值为null ) (到终点) -
原型链:这些对象及原型对象通过
__proto__属性链接形成的链路结构就行原型链。原型链是由多级父对象逐级继承形成的。原型链保存着一个对象可用的所有属性和方法。原型链控制着属性和方法的使用顺序:就近原则--先子级后父级 -
关系:
instance.constructor.prototype = instance.__proto__实例的构造函数的原型对象prototype就是实例对象的原型proto
- 实例通过
new 构造函数()得到 - 实例的
constructor是构造函数 - 实例的原型
__proto__就是构造函数的原型对象prototype - 构造函数
constructor与prototype是一对相互反指的
看一下下面的例子帮助理解:
function Person(name) { // 构造函数 this.name = name } var lisa = new Person('lisa') // 生成实例对象 // 1.函数的prototype原型对象的构造函数是自身 Person.prototype.constructor === Person // true // 2.实例与构造函数之间的关系 lisa.constructor === Person // true lisa.__proto__ === Person.prototype // true lisa.__proto__ === lisa.constructor.prototype // true // 3.构造函数与内置类型Function的关系(function定义的时候相当于new Function()操作) Person.constructor === Function // true Person.__proto__ === Function.prototype // true Person.__proto__ === Person.constructor.prototype // true // 直接定义对象与内置类型Object的关系 var obj = {} // 直接定义对象相当于new Object()操作 obj.constructor === Object // true obj.__proto__ === Object.prototype // true - 实例通过
内置类型Function、Object、Array、Date等都是函数,且可以做构造函数,它们之间的关系: 所有对象和Object这个构造函数的原型对象prototype最终都指向Object.prototype而Object.prototype这个对象的原型指向null(终点)。
// 1. 特殊函数Function
Function.constructor === Function
Function.prototype === Function.__proto__
Function.prototype.__proto__ === Object.prototype
// 可以理解为:Function既是构造函数又是自己的实例
// 所以Function作为构造函数时的原型对象(prototype)就是Function作为实例时的原型__proto__
// Function.prototype原型对象也是对象,所以这个对象的原型就是Object.prototype
// 2. 特殊对象Object.prototype与构造函数Object
Object.constructor === Function
Object.prototype.constructor === Object
// Object.prototype原型对象也是对象
// Object.prototype作为对象时的构造函数就是Object
Object.prototype === Object.prototype
// 上式可以理解为:构造函数Object的原型对象prototype 就是 Object.prototype这个对象
// 3. 其他内置类型(函数)的构造函数都是Function
Array.constructor === Function
Date.constructor === Function
Array.__proto__ === Function.prototype
Date.__proto__ === Function.prototype
Array.prototype.__proto__ === Object.prototype
Date.prototype.__proto__ === Object.prototype
// Array/Dat是函数,可以看作new Function()得到的实例
// 它们的构造函数都是Function
// 它们作为实例时的原型__proto__就是其构造函数的原型对象Function.prototype
// 它们作为构造函数时的原型对象Array.prototype这个对象的原型__proto__就是Object.prototype
// 4. 内置类型创建的实例(以数组为例)
[].constructor === Array // 直接定义数组[]相当于new Array()操作
[]__proto__ === Array.prototype // 实例的原型__proto__是其构造函数的prototype
[].__proto__.__proto__ === Object.prototype
结合以上,我们来看原型链:
function Person() {}
var lili = new Person()
lili.__proto__ === Person.prototype // 实例原型是构造函数的原型对象
Person.prototype.__proto__ === Object.prototype
// Person没有自定的父类了,Person.prototype是对象,所以其父类就是Object
lili.__proto__.proto__ === Object.prototype
lili.__proto__.proto__.__proto__ === null
// 这个一直向上查找原型__proto__直到null的链路就是原型链
总结
- 任何对象都有其原型
__proto__属性,函数有作为对象的__proto__属性也有作为函数的prototype属性。 - (构造函数创建出来的)实例对象的原型
__proto__是其构造函数的原型对象prototype - 函数的原型对象的构造函数是其自身
fun.prototype.constructor===fun Object.prototype这个对象的原型是null(原型链的终点)