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

这可能是最好最通俗易懂的讲“原型链”的方式,有练习!

时间:2023-03-27 01:55:59 JavaScript

前言大家好,我是林三信,相信大家都听说过前端三座大山:闭包、原型链、作用域,这三者其实只是基础。而且我总觉得基础是进阶的前提,所以不能因为是基础就忽视了。今天我就用我的方式来说说原型链。希望大家能够牢牢掌握原型链的知识。很多文章一上来就扔这张图,但我不喜欢这样。我认为这对基础差的学生不好。我喜欢带领大家从零开始实现这张图,并在实现的过程中不断掌握原型链的所有知识!!!来吧!!!跟着我从零开始实现吧!!!跟我来驯服原型链吧!!!什么是原型和__proto__?这两件事是什么?prototype:显式原型__proto__:隐式原型是什么关系?那么这两个就叫做原型,那么它们之间是什么关系呢?通常,构造函数的原型和其实例的__proto__指向同一个地方,称为原型对象。那么什么是构造器呢?俗话说,能用new的函数叫构造函数,不能用箭头函数做构造函数。functionPerson(name,age){//这是构造函数this.name=namethis.age=age}constperson1=newPerson('Xiaoming',20)//这是Person构造函数的实例constperson2=newPerson('Xiaohong',30)//这也是Person构造函数的实例构造函数的原型和它的实例__proto__指向同一个地方,我们可以验证functionPerson(name,age){this.name=namethis.age=age}Person.prototype.sayName=function(){console.log(this.name)}console.log(Person.prototype)//{sayName:[Function]}constperson1=newPerson('小明',20)console.log(person1.__proto__)//{sayName:[Function]}constperson2=newPerson('小红',30)console.log(person2.__proto__)//{sayName:[Function]}console.log(Person.prototype===person1.__proto__)//trueconsole.log(Person.prototype===person2.__proto__)//truefunction上面我们提到了构造函数,其实归根结底也是一个函数,其实我们通常定义函数,无非就是下面的函数fn1(name,age){console.log(`我是${name},我是${age}岁`)}fn1('林三鑫',10)//我是林三鑫,我10岁constfn2=function(name,age){console.log(`我是${name},我是${age}岁`)}fn2('林三鑫',10)//我是林三新,我10岁constarrowFn=(name,age)=>{console.log(`我是${name},我是${age}岁`)}arrowFn('林三鑫',10)//我是林三鑫,今年10岁。其实这些类型的本质是一样的(只考虑函数的声明),都可以使用newFunction来声明。是的,函数也是构造函数上面的写法相当于下面的写法constfn1=newFunction('name','age','console.log(`我是${name},我是${age}岁`)')fn1('林三心',10)//我是林三心,我10岁constfn2=newFunction('name','age','console.log(`我是${name},Iam${agethisyear}yearold`)')fn2('林三鑫',10)//我是林三鑫,今年10岁constarrowFn=newFunction('name','age','console.log(`我是${name},我是${age}岁`)')arrowFn('林三鑫',10)//我是林三鑫,我今年10岁我们之前说过构造函数的原型和它的实例__proto__指向同一个地方。这里的fn1、fn2、arrowFn其实就是Function构造函数的实例,我们来验证一下。functionfn1(name,age){console.log(`我是${name},我是${age}岁`)}constfn2=function(name,age){console.log(`我是${name},我是${age}岁`)}constarrowFn=(name,age)=>{console.log(`我是${name},我是${age}岁`)}console.log(Function.prototype===fn1.__proto__)//trueconsole.log(Function.prototype===fn2.__proto__)//trueconsole.log(Function.prototype===arrowFn.__proto__)//trueobject在我们的在平时的开发中,我们通常使用以下方法来创建对象。构造函数创建一个对象,它创建的对象都是这个Function构造函数的实例,这里不讨论。对象的字面创建newObject创建一个对象Object.create创建一个对象,它创建一个原型为空的对象。讨论一下//第一种:构造函数创建一个对象functionPerson(name,age){this.name=namethis.age=age}constperson1=newPerson('林三鑫',10)console.log(person1)//Person{name:'林三鑫',age:10}//第二种:创建对象constperson2={name:'林三鑫',age:10}console.log(person2)//{name:'林三鑫',age:10}//第三种:newObject创建一个对象constperson3=newObject()person3.name='林三鑫'person3.age=10console.log(person3)//{name:'林三鑫',age:10}//第四种:Object.create创建一个对象constperson4=Object.create({})person4.name='林三鑫'person4.age=10console.log(person4)//{name:'林三鑫',age:10}我们先来看看用字面量创建对象和用newObject创建对象的两种方式。其实用字面量创建对象的本质就是用newObject创建对象//字面量创建对象constperson2={name:'林三鑫',age:10}console.log(person2)//{name:'林Sanxin',age:10}本质是//newObject创建对象constperson2=newObject()person2.name='林三鑫'person2.age=10console.log(person2)//{name:'林三鑫',age:10}我们之前说过,构造函数的原型和它的__实例proto__指向同一个地方。这里的Person2和person3实际上是Object构造函数的实例。让我们验证一下。constperson2={name:'林三鑫',age:10}constperson3=newObject()person3.name='林三鑫'person3.age=10console.log(Object.prototype===person2.__proto__)//trueconsole.log(Object.prototype===person3.__proto__)//trueFunction和Object上面我们常说函数是Function构造函数的实例,对象是Object构造函数的实例,那么这两个实例是谁函数构造函数和对象构造函数?functionObject()实际上是一个函数,所以它是Function构造函数的一个实例。functionFunction()实际上是一个函数,所以它也是Function构造函数的一个实例。是的,它是它自己的一个实例。我们可以试试看。知乎console.log(Function.prototype===Object.__proto__)//trueconsole.log(Function.prototype===Function.__proto__)//trueconstructor构造函数和prototype是一对,你指向我,我指向你For例如,如果你是我的妻子,那么我一定是你的丈夫。functionfn(){}console.log(fn.prototype)//{constructor:fn}console.log(fn.prototype.constructor===fn)//真正的原型链Person.prototype和Function.prototype讨论原型chain之前先说一下这两个东西Person.prototype,也就是构造函数Person的原型对象Function.prototype,也就是构造函数Function的原型对象。我们说过原型对象,原型对象,大家可以知道,这两者的本质都是对象。既然是对象,本质上肯定是通过newObject()创建的。由于是newObject()创建的,也就是说Person.prototype和Function.prototype都是构造函数Object的实例。它还表明Person.prototype和Function.prototype的__proto__都指向Object.prototype。我们可以验证functionPerson(){}console.log(Person.prototype.__proto__===Object.prototype)//trueconsole.log(Function.prototype.__proto__===Object.prototype)//true什么是原型链?什么是原型链?其实,俗话说:__proto__的路径称为原型链的末端。正如我们在上面看到的,三个原型链的末端是Object.prototype。这是否意味着Object.prototype是原型链的末端?其实不是,Object.prototype还有__proto__,它指向null,也就是原型链的末端。至此,整个原型原理图就完成了!!!原型继承说到原型,不得不补充一下原型继承的知识。原型继承是指实例可以在构造函数上使用原型中的方法functionPerson(name){//constructorthis.name=name}Person.prototype.sayName=function(){//将方法添加到原型对象控制台.log(this.name)}constperson=newPerson('林三鑫')//实例//使用原型方法person.sayName()中的构造函数//林三鑫instanceof使用方法AinstanceofB函数:判断B的原型是否在A实例的原型链上//trueconsole.log(PersoninstanceofObject)//trueconsole.log(personinstanceofPerson)//trueconsole.log(personinstanceofObject)//真正的习题习题仅供大家巩固本文知识第一题varF=function(){};Object.prototype.a=function(){console.log('a');};Function.prototype.b=function(){console.log('b');}varf=newF();f.a();f.b();F.a();F.b();回答f.a();//af.b();//f.b不是一个函数F.a();//aF.b();//b第二题varA=function(){};A.prototype.n=1;varb=newA();A.prototype={n:2,m:3}varc=newA();console.log(b.n);console.log(b.m);控制台日志(c.n);控制台日志(c.m);回答console.log(b.n);//1console.log(b.m);//undefinedconsole.log(c.n);//2console.log(c.m);//第三个问题varfoo={},F=function(){};Object.prototype.a='valuea';Function.prototype.b='valueb';console.log(foo.a);console.log(foo.b);console.log(F.a);console.log(F.b);answerconsole.log(foo.a);//值aconsole.log(foo.b);//undefinedconsole.log(F.a);//值aconsole.log(F.b);//valueb第四题functionA(){}functionB(a){this.a=a;}functionC(a){if(a){这个.a=a;}}A.prototype.a=1;B.prototype.a=1;C.prototype.a=1;console.log(newA().a);console.log(newB().a);console.log(新C(2).a);回答console.log(newA().a);//1console.log(newB().a);//未定义控制台。日志(新C(2).a);//2题5console.log(123['toString'].length+123)答案:123是一个数字,数字的本质是newNumber(),数字本身没有toString方法,去沿__proto__查找函数Number()的原型并找到toString方法。toString方法的长度是1,1+123=124。至于为什么长度是1,可以看到95%的人回答没有出现的问题:函数的长度是多少?console.log(123['toString'].length+123)//124结语觉得这篇文章对你有帮助,点个赞,鼓励一下林三心哈哈或者加我群哈哈,一起摸鱼一起学习