原型和原型链

65 阅读2分钟

原型和原型链

当查找一个对象的属性的时候,如果该对象上没有这个属性,则会去该对象上面的原型对象上查找,直到找到最顶层,如果还没有,则为undefined,原型的顶点是null

ES 5中提供了Object.create(原型,{新值})方法来克隆对象,

var Person = {
    sex: '男'
}
​
var zs = Object.create(Person,{
    name: {
        value: '张三',
        enumerable: true
    }
})
log(zs.sex) //男
log(zs.__proto__ === Person) //truevar zs_son = Object.create(zs,{
    birth: {
        value: '1999',
        enumerable: true
    }
})
log(zs_son.sex) //男
log(zs_son.name) //张三
log(zs_son.__proto__ === zs) //true
log(zs_son.__proto__.__proto__ === Person) //true

再之后出现了通过构造函数来模拟类的形式来生成对象——new关键字

这种方式还是基于原型来创建的对象

function Person(name,age){
    this.name = name;
    this.age = age;
}
​
var zs = new Person('张三',18)
var ls = new Person('李四',20)
log(zs) //Person {name:'张三',age:18}

对象除了属性,还有方法,方法一般直接挂在原型对象上

Person.prototype.showAge = function(){
    console.log(`${this.name}今年${this.age}岁`)
}
zs.showAge() //张三今年18岁
log(zs.__proto__ === Person.prototype)//true
log(zx.constructor === Person) //true

Person.prototype实际就是Person实例对象的原型对象

  • JavaScript 中每个对象都有一个原型对象。可以通过proto属性来访问到对象的原型对象
  • 构造函数的 prototype 属性指向一个对象,这个对象是该构造函数实例化出来的对象的原型对象。
  • 原型对象的 constructor属性也指向其构造函数。
  • 实例对象的 constructor 属性是从它的原型对象上面访问到。

原型的顶点是null

log(zs_son.__proto__.__proto__.__proto__) //null
log(zs_son.__proto__.__proto__ === Object.prototype) //true
log(Object.prototype.__proto__) // null

完整的原型图

原型链.jpg

总结

  • 每个对象都有一个 proto 属性,该属性指向自己的原型对象
  • 每个构造函数都有一个prototype属性,该属性指向实例对象的原型对象
  • 原型对象里的constructor指向构造函数本身

每个对象都有自己的原型对象,而原型对象本身,也有自己的原型对象,从而形成一条原型链

当访问一个对象的属性时,不仅在该对象上查找,还会查找该对象的原型对象,以及原型的原型,依次向上,直到找到与之匹配的 或 到达原型链顶端

  • 对一个构造函数实例化后,他的原型指向什么?

指向该构造函数实例化出来对象的原型对象

对于构造函数来讲,可以通过prototype访问到该对象

对于实例对象来讲,可以通过属性 __ proto__来访问到