什么是原型
每一个javascript对象(除null外)创建的时候,就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。
这么说可能会有点抽象,举个例子吧
function Person(age) {
this.age = age
}
Person.prototype.name = 'Bob'
var person1 = new Person()
console.log(person1.name) //Bob
在通过构造函数创建实例的时候,如果去实例中找寻某个属性值的时候,如果他有的话就会直接输出,如果没有的话,就会去它的原型对象中去找。
prototype
:每个函数都有一个prototype属性,这个属性指向函数的原型对象。
__proto__
:这是每个对象(除null外)都会有的属性,叫做__proto__
,这个属性会指向该对象的原型。
constructor
:每个原型都有一个constructor
属性,指向该关联的构造函数。
console.log(Person===Person.prototype.constructor) // true
console.log(person.__proto__ == Person.prototype) // true
console.log(person.__proto__.constructor == Person) // true
console.log(person.constructor == Person) // true
为什么 person.constructor == Person
,其实还是前面所说到的,因为person没有这个属性的情况下,会从它的原型中去继承,这个时候第三个式子和第四个式子就是一样的了。
原型的使用
示例
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
this.sayName = function () {
console.log("我的名字叫" + this.name);
}
}
在上面代码中sayName ,每创建一个Person构造函数,在Person构造函数中,为每一个对象都添加了一个sayName方法,也就是说构造函数每执行一次就会创建一个新的sayName方法。
这时就体现出原型的好处了把sayName方法放到构造函数的prototype上,这时候只需要创建一个,而且每一个实例都可以访问到。
什么是原型链
构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。当将原型对象等于另一个类型的实例,原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。
简单的说:上边说道如果实例没有一个属性,它会去它的原型中去找,但是如果它的原型中也没有这个属性呢,会停止寻找么,不一定,因为它的原型可能也有自己的原型,这个时候他就会去它的原型的原型中去寻找,这个时候会停下么,还是不一定,要看他原型的原型有没有原型,这样就形成了一条原型链。当然,若最后一个找不到原型时,会返回null