当前位置: 首页 > Web前端 > JavaScript

如何理解Js中的原型链?(一起来学习吧)

时间:2023-03-27 11:13:55 JavaScript

示例varanimal=function(){};vardog=function(){};animal.prototype.price=20;animal.price=1000;dog.prototype=animal;varcat=newanimal();vartidy=newdog();//以下两行输出什么?console.log(cat.price);console.log(tidy.price);要理解原型和原型链,首先要知道几个概念:在js中,继承机制是原型继承。继承的起点是对象原型(Objectprototype)。万物皆对象,只要是对象,都会有一个proto属性,里面存放着指向其构造的指针。对象原型也是proto指向null的对象。有两种类型的对象:函数对象和普通对象。只有函数对象才有“原型”对象(prototype)。原型的本质是一个普通的对象。函数原型比较特殊,它是一个没有原型的函数对象。new操作得到的对象是普通对象。当调用一个对象的属性时,它会先在自身中查找。如果没有,则根据proto寻找构造原型。没有人就继续往上看。最后会到达顶层的Object原型,它的proto指向null。如果没有结果,则返回undefined并结束。proto链接的路径就是“原型链”。看图,cat调用price来检查自己。没有价格,根据proto找到动物原型对象。price是在animal原型对象中找的,所以cat.price返回20。如果没有animal.prototype=20,会根据animal原型对象的proto找Object原型,Object原型中的proto指向空。如果仍未找到价格,则结果将不确定。tidy调用price查看自己,没有price,根据proto找到dog原型。dogprototype=animal,这里可以这样理解:prototype本质上也是一个对象,所以一个对象是可以重新赋值的,不管是函数对象还是普通对象。事实上,每个原型都会有一个预定义的构造函数属性来引用它的函数对象。price是在animal中找的,所以tidy.price为1000,如果没有animal.price=1000,则根据animal的proto找下一个对象,最后找不到price,结果将是未定义的。进阶学习:创建对象的方式{},newObject()构造函数Object.create()这个方法改变了新对象的proto,指向create的输入对象。instanceofVSconstructorinstanceof原理:检查左对象和右对象是否在同一个原型链上。构造函数原理:在对象的proto属性所指向的原型对象上取构造函数字段。catinstanceofanimal===truecat.__proto__===animal.prototypeanimal.prototypeinstanceofObject===trueanimal.prototype.__proto__===Object.prototypecatinstanceofObject===true//但是,cat.constructor===animal//truecat.constructor===Object//falsenew运算符的原理是创建一个空对象,其proto等于构造函数的原型对象(可以用Object.create()来完成)。构造函数以步骤1创建的对象为上下文,是否返回对象如果步骤2返回对象,则使用该对象作为新实例,否则使用步骤1创建的对象作为新实例varmyNew=function(func){varo=Object.create(func.prototype)vari=func.call(o)returntypeofi==='object'?i:o}继承类声明:functionclassgeneratesinstance:new继承的几种方式:借助构造函数,父类作用域指向子类Parent.call(this)//this是子类的上下文缺点:不能借助原型链继承原型链属性Child.prototype=newParent()缺点:子类的所有实例共享原型对象;子类实例构造函数是Parent组合方法Parent.call(this)//this是Child类的上下文Child.prototype=Object.create(Parent.prototype)Child.prototype.constructor=Child