原型链

原型、构造函数、实例、原型链的关系

对象/实例 通过 __proto__ 访问原型链上的原型对象,对象没有prototype这个属性

构造函数 通过 prototype 访问原型链上的原型对象

任何对象或函数都有constructor属性,对象的constructor为它的构造函数或Object(),函数的constructor为Function()

所有对象的原型链顶端都是Object原始对象 {constructor: ƒ, defineGetter: ƒ, defineSetter: ƒ, hasOwnProperty: ƒ, lookupGetter: ƒ, …}

1

创建对象的几种方法

// 通过字面量创建,往上只有一个原型对象,和new Object()原理一样
var o1 = { name: 'o1' }
console.log(o1) // Object {name:'o1'}
console.log(o1.__proto__) // {constructor: ƒ, hasOwnProperty: ƒ, …}
console.log(o1.__proto__.__proto__) // null
console.log(o1.__proto__.constructor === Object) // true 其实就是隐式的通过Object构造函数创建的

// 通过构造函数创建,往上有两个原型对象
var M = function () { this.name = 'o2' }
var o2 = new M()
console.log(o2) // M {name: 'o2'}
console.log(o2.__proto__) // {constructor: ƒ}
console.log(o2.__proto__.constructor === M) // true
console.log(o2.__proto__.__proto__) // {constructor: ƒ, hasOwnProperty: ƒ, …}
console.log(M.__proto__ === Function.prototype) // true 函数也是对象,M函数是Function构造函数的一个实例

// 通过Object构造函数创建,往上只有一个原型对象
var o3 = new Object({ name: 'o3' })
console.log(o3) // Object {name:'o3'}
console.log(o3.__proto__) // {constructor: ƒ, hasOwnProperty: ƒ, …}
console.log(o3.__proto__.__proto__) // null
console.log(o3.__proto__.constructor === Object) // true

// 通过Object.create方法创建,直接打印看不到属性,但通过原型链可以访问到,原理是该方法会创建一个新对象,然后新对象的原型链指向P
var P = { name: 'o4' }
var o4 = Object.create(P)
console.log(o4) // Object {} 
console.log(o4.name) // o4
console.log(o4.__proto__ === P) // true
console.log(o4.__proto__.__proto__) // {constructor: ƒ, hasOwnProperty: ƒ, …}