1. 首先,我们创建一个构造函数
function Person(){
this.name = 'jinlong'
}
2. 然后,我们基于构造函数Person创建一个实例对象
const person = new Person()
console.log(person.name)
3. 如果,我们访问person对象中不存在的属性showName会怎么样呢?
console.log(person.showName)
4. 现在,我们给构造函数的原型添加一个属性
Person.prototype.showName = function(){
console.log(`我的名字是${this.name}`)
}
console.log(person.showName())
5. 很明显,第二次打印的时候,调用了构造函数原型的属性showName。那么为什么会这样呢?
5.1 首先,每个对象都有一个隐藏属性叫做隐式原型"proto"。
5.2 当我们访问对象的某个属性时,如果在对象里面找不到该属性,就会通过"proto"来查找。
5.3 而"proto"指向构造函数的显示原型"prototype",而prototype本身也是个对象,它除了有一个constructor属性指向构造函数外,它也会有一个隐式原型"proto",它会顺着这条线一直往上找,直到找到为止,最终找到Object.prototype里面。
5.4 如果还找不到就会指向终点null,意为找不到该对象。
6. 现在,我们来测试一下,看是否属实
console.log(person.__proto__ === Person.prototype)
console.log('constructor', Person.prototype.constructor === Person)
console.log(person.toString())
console.log('null', Object.prototype.__proto__ === null)
console.log(Person.prototype.__proto__ === Object.prototype)
总结:上面这些一层层的查找,就像是通过一根链子一步一步往上找,所以也叫做原型链。
7. 说了这么多废话,最后还是来看看下面这张图比较直观