前端⾯试题:JS中的原型和原型链
JS的原型和原型链算是前端⾯试题的热门题⽬了,也是参加了⼏场⾯试,感觉好多次都被问到对原型和原型链的理解,所以今天也是索性把他给整理出来,⼀⽅⾯⽅便⾃⼰以后复习查看,另⼀⽅⾯也是给⼤家分享⼀下我对原型和原型链的理解。
ES6之前中并没有引⼊类(class)的概念,JavaScript并⾮通过类⽽是直接通过构造函数来创建实例。
什么是原型
每⼀个javascript对象(除null外)创建的时候,就会与之关联另⼀个对象,这个对象就是我们所说的原型,每⼀个对象都会从原型
中“继承”属性。
这么说可能会有点抽象,举个例⼦吧
function Person(age) {
this.age = age
}
Person.prototype.name = 'kavin'
var person1 = new Person()
console.log(person1.name)  //kavin
就是说在通过构造函数创建实例的时候,如果去实例中寻某个属性值的时候,如果他有的话就会直接输出,如果没有的话,就会去它的原型对象中去。
prototype:每个函数都有⼀个prototype属性,这个属性指向函数的原型对象。
__proto__:这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。
constructor:每个原型都有⼀个constructor属性,指向该关联的构造函数。
原型相关的知识考点⼀般就是围绕这张图,那怎么去验证这张图的正确性呢?
console.log(Person===structor)  // true
console.log(person.__proto__ == Person.prototype) // true
console.log(person.__proto__.constructor == Person) // true
console.structor == Person) // true
估计⼤家看到底四个的时候会有⼀些疑问了,为什么structor == Person,其实还是前⾯所说到的,因为person没有这个属性的情况下,会从它的原型中去继承,这个时候第三个式⼦和第四个式⼦就是⼀样的了。
什么时候会⽤到原型
下⾯说⼀下什么时候会⽤到原型,还是像上边⼀样,举个简单的例⼦:
function Person(name, age, gender) {
this.name = name
this.age = age
this.sayName = function () {
console.log("我的名字叫" + this.name);
}
}
这和上边看起来是没什么区别的,但是⼩差别就在这个sayName ,就是说每创建⼀个Person构造函数,在Person构造函数中,为每⼀个对象都添加了⼀个sayName⽅法,也就是说构造函数每执⾏⼀次就会创建⼀个新的sayName⽅法。
⼀个还好,如果创建了⼀百个实例,⼀千个甚⾄上万个呢,这时候就体现出原型的好处了,我们可以把sayName⽅法放到构造函数的prototype上,这时候只需要创建⼀个,⽽且每⼀个实例都可以访问到。
原生js和js的区别什么是原型链
单的回顾⼀下构造函数、原型和实例的关系:每个构造函数都有⼀个原型对象,原型对象都包含⼀个指向构造函数的指针,⽽实例都包含⼀个指向原型对象的内部指针。那么假如我们让原型对象等于另⼀个类型的实例,结果会怎样?显然,此时的原型对象将包含⼀个指向另⼀个原型的指针,相应地,另⼀个原型中也包含着⼀个指向另⼀个构造函数的指针。假如另⼀个原型⼜是另⼀个类型的实例,那么上述关系依然成⽴。如此层层递进,就构成了实例与原型的链条。
简单的表达就是:上边说道如果实例没有⼀个属性,它会去它的原型中去,但是如果它的原型中也没有这个属性呢,会停⽌寻么,不⼀定,因为它的原型可能也有⾃⼰的原型,这个时候他就会去它的原型的原型中去寻,这个时候会停下么,还是不⼀定,要看他原型的原型有没有原型,这样就形成了⼀条原型链。
直到最后⼀个不到原型时返回null