,验证前言是否完整掌握一个知识点的最好方法就是你能不能用自己的语言表达出来。原型和原型链一直是学习JS绕不过去的知识点。其中proto和prototype是最麻烦的。这里我简单写下自己的理解,从prototype和prototype链上拆解proto和prototype。希望对大家有所帮助。帮助。一、原型1、在javascript中定义,函数可以有属性。每个函数都有一个特殊的属性叫做原型(prototype)注:原型属性是函数独有的,对象没有这个属性。什么是原型(prototype),有哪些属性?来吧,我们举一个具体的例子:functionfn(){};console.dir(fn)这里我们可以看出原型(prototype)是一个对象。对于当前示例,有两个构造函数和原型。属性。这个原型对象的作用是什么?来,我们继续往下看~2、使用现在我们知道了原型是一个对象,那么原型对象的作用是什么呢?事实上,原型是ECMAScript实现继承时产生的一个概念。这里我们简单的以ES5对象为例:}letperson=newPerson('小明');person.say();//我叫小明让我们一步一步解释这个例子:声明一个构造函数Person,它的原型上有一个属性名称声明一个函数say实例和一个Person类-person调用person的say方法我们找到了那个person可以在其构造函数的原型中调用say方法,为什么?让我们看看person是什么:虽然实例person本身没有say方法,但它可以通过proto属性访问其原型中的say方法。为什么proto属性指向其构造函数的prototype原型,它们之间是什么关系?我们继续往下看~2.原型链1、__proto__在介绍原型链之前,我们先来看一个属性:proto,这是一个和原型prototype非常相似的属性。这一次,让我们彻底了解他们之间的关系。我们先看MDN上的定义:Object.prototype的proto属性是一个accessor属性(一个getter函数和一个setter函数),暴露了内部的[[Prototype]](一个对象或null)。注意:函数也是对象的一种,所以它同时具有prototype和__proto__两个属性。如果你不理解这个定义也没关系。让我们举例说明:letobj={a:1};console.log(obj);我们可以看到proto指向了一个对象,这个对象是什么?来,我们继续看classParent{constructor(name){this.name=name;}print(){console.log(this.name);}}letparent=newParent('Xiaoming');console.dir(parent);console.dir(Parent);嘿嘿,有没有发现parent.__proto__和Parent.prototype指向的对象很像,do你知道它们是否是同一个对象吗?parent.__proto__==Parent.prototype//trueresult是同一个引用,此时我们可以得出结论:实例的__proto__属性指向其构造函数的原型。那么他们之间的这种关系有什么作用呢?这就涉及到原型链。2.原型链一个JavaScript对象有一个指向原型对象的链。当尝试访问对象的属性时,它不仅会在对象上搜索,还会在对象的原型上搜索,然后在对象原型的原型上搜索,依此类推,直到找到具有匹配名称的属性或到达原型链的末端。注意:因为对象没有prototype属性,所以通过__proto__属性将文字描述与prototype关联起来,非常抽象。我们通过ES5继承来具体分析一下:call(this,name);}Child.prototype=Object.create(Parent.prototype);Child.prototype。constructor=Child;letchild=newChild('Xiaoming');console.log(child);看看child里面有什么这里可能有些同学对Object.create()函数不太熟悉。明白它是干什么的,别着急,我们来看它的源码实现:functioncreate(proto){functionF();F.原型=原型;returnnewF();}声明了一个构造函数F,然后将其原型指向参数proto,并返回构造函数的一个实例。好了,我们来看看整个过程:1.声明Parent构造函数2.声明Child构造函数并手动绑定this指向3.执行Object.create(Parent.prototype):声明一个构造函数F,改变其原型prototype指向(F.prototype=Parent.prototype),然后返回F的实例f。注意这一步其实就是f.__proto__==F.prototype4,将Child的prototype指向f.prototype5,并绑定Child的ConstructorLet我们再看一下child.print()的调用过程。child对象中没有print函数,所以我们在它的prototype上查找:child.__proto__——>f.prototype2,输入f.prototype查找print函数,没有找到,于是在它的prototype上查找:f.__proto__——>F.prototype3,F.prototype==Parent.prototype,于是进Parent.prototype找打印函数,有打印函数,调用成功怎么样,是不是突然清除!原型链实际上是通过proto和prototype之间的关系连接起来的,这样对象就可以在自己的原型上找到方法和属性。详细关系描述如下:实战让我们看一道面试题:varF=function(){};Object.prototype.a=function(){console.log('a');};Function。原型。b=function(){console.log('b');}varf=newF();f.a();f.b();F.a();F.b();解题思路如下:1.f.a()——>实例f调用了a方法,但是它没有,所以从它的原型上查找:f.__proto__==F。prototype2.F.prototype中没有方法,继续在它的prototype中查找,F.prototype.__proto__==Object.prototype3.Object.prototype中有方法,但是没有b方法,所以f.a()的结果是a,调用f.b()会报错:f.bisnotafunction4.f.a():构造函数调用了a方法,它本身没有,从中查找它的原型:F.__proto__==Funtion.prototype5.Funtion.prototype中有b方法,所以F.b()的输出是b。如果没有方法,继续在其原型中查找,Function.prototype.__proto__==Object.prototype6.Object.prototype中有方法,所以F.a()的输出是一个3.总结一下关系__proto__和prototype在这篇文章中我简单梳理了一下它们之间的关系,写下自己的理解,提供一个思路供大家理解。当然,可能会有不准确或错误的描述。欢迎大家留言交流,以上~
