首先我们用构造函数创建一个函数:
function Person(){
this.name="Tom"
}
let person =new Person()
console.log(person.name)//Tom
在上面的例子中,Person是一个构造函数,我们用new创建了一个对象person,对象继承了构造函数的属性name,然后我们在创建一个函数来介绍prototype:
function Person(){
}
Person.prototype.color='yellow'
let person1=new Person()
let person2=new Person()
person1.color//"yellow"
person2.color//"yellow"
通过上面我们可以发现person1和person2有着相同的属性值,而这个属性值是通过构造函数Person里面的属性prototype所指向的对象的属性,其实prototype所指向的对象就是我们创建的对象的原型
什么叫原型呢?按我的理解就是在所有的对象闯进创建一开始就有一个与之有关联的另一个对象,这个对象里面有很多共有的属性,每一个对象都会在原型里”继承“属性。
另外我们知道所有的JS对象都有一个属性:__proto__,这个属性指向该对象的原型。我们有一个公式:对象.__proto__=其构造函数的.prototype,翻译下就是:你是谁构造的你的原型就是谁的prototype属性对应的对象。我们来验证一下:
function Person(){
}
let person=new Person()
undefined
person.__proto__===Person.prototype//true
由此可见,我们的想法是对的。
所以我们得到关系图如下:
当我们读取对象的属性是,如果该对象有直接可以读取,如果没有,就会查找于对象相关连的原型里面的属性,如果还找不到,就会去原型的原型,直到顶层为止(null)
function Person(){
}
let person=new Person()
Person.prototype.name='jay'
person.name='leehome'
person.name//"leehome"
delete person.name//true
person.name//"jay"
person.age//undefined
有上面可以看出:当我们给person添加了一个name属性,读取name的属性的时候自然打印的是自身的name属性,当我们把自身name属性删除的时候,再次读取就会去原型里面查找,然后有就读取。
如果没有找到就会去原型的原型里面找,我们知道Person.prototype也是个对象,所有的对象是通过Object构造函数生成的,再通过上面的公式对象.__proto__=其构造函数的.prototype所以Person.prototype.__proto__=Object.prototype,也就是说Person.prototype的原型就是Object.prototype。我们可以验证:
所以我们可以知道:
那可能就有人问了,Object.prototype的原型是什么呢?
没错就是null,null就是没有对象。由此我们可以得到一条原型链: