原型和原型链
当查找一个对象的属性的时候,如果该对象上没有这个属性,则会去该对象上面的原型对象上查找,直到找到最顶层,如果还没有,则为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) //true
var 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
完整的原型图
总结
- 每个对象都有一个 proto 属性,该属性指向自己的原型对象
- 每个构造函数都有一个prototype属性,该属性指向实例对象的原型对象
- 原型对象里的constructor指向构造函数本身
每个对象都有自己的原型对象,而原型对象本身,也有自己的原型对象,从而形成一条原型链
当访问一个对象的属性时,不仅在该对象上查找,还会查找该对象的原型对象,以及原型的原型,依次向上,直到找到与之匹配的 或 到达原型链顶端
- 对一个构造函数实例化后,他的原型指向什么?
指向该构造函数实例化出来对象的原型对象
对于构造函数来讲,可以通过prototype访问到该对象
对于实例对象来讲,可以通过属性 __ proto__来访问到