JavaScript中的原型与原型链

Faustine ·
更新时间:2024-11-14
· 596 次阅读

文章目录1.构造函数2.prototype与proto3.原型链
欢迎大家关注我的公众号,共同交流,共同成长~
欢迎大家关注我的公众号,共同交流,共同成长~
在刚接触JavaScript的对象的时候,我的内心是懵逼的,什么原型、原型链,好像跟我之前学的其他语言的对象不太一样,今天我们就来好好捋一捋JavaScript中的原型与原型链。

在一般进行对象定义时,我们往往会首先定义一个类作为现实世界的抽象,然后由类来进行对象的实例化,然而在JS(ES5)中是没有class这个类型的,而是由构造函数、原型以及原型链实现了对象的定义以及继承等。

1.构造函数 function Fruit(name){ this.name=name }; var grape=new Fruit("grape") grape.color="purple"; console.log(grape.name,grape.color); // grape purple

上面的Fruit函数即为一个构造函数,我们通过一个new+构造函数的形式来建立了一个对象实例grape,并通过构造函数name参数将grape对象名字设置为“grape”,然后又通过obj.property=value的形式将grape实例的color属性设置为“purple”。

2.prototype与proto

prototype函数的一个属性,并且每个函数都有这个属性,当将其作为构造函数进行对象实例创建的时候,便会将该实例的原型(proto)设置为prototype,并且这些创建的实例共享原型对象的属性,从而实现了继承的效果。

function Fruit(name){ this.name=name }; Fruit.prototype.color="red"; var melon=new Fruit("melon"); var apple=new Fruit("apple"); console.log(melon.color,apple.color); // red red

我们将Fruit函数的prototype的color属性设置为“red”,然后由Fruit函数创建的实例都继承了这个属性,将其color进行输出,都输出为red。

__proto__则是属于对象的一个属性,除了null对象为,所有的对象都有__proto__这个属性,这个属性指向了对象的原型,也就是说,构造函数的prototype属性与该构造函数创造出的实例的__proto__属性是完全相同的两个属性,我们通过以下代码来验证:

function Fruit(name){ this.name=name }; var grape=new Fruit("grape") console.log(Fruit.prototype===grape.__proto__) //true

另外每一个构造函数的prototype属性代表的原型都有一个constructor属性,该属性指向了此构造函数。通过以下代码来验证:

function Fruit(name){ this.name=name }; var grape=new Fruit("grape") console.log(Fruit.prototype.constructor===Fruit) //true

接下来我们通过一幅图来更清楚地表明构造函数、对象实例、prototype、__proto__之间的关系。

在这里插入图片描述

3.原型链

首先解释一下什么是原型链, 每个对象都可以有一个原型__proto__,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找… 这个操作被委托在整个原型链上,这个就是我们说的原型链了。

接下来我们通过代码来具体了解一下原型链到底是什么,这次我们换一个中国男老师的例子来感受。

//中国人的类 function Person(){ this.country="China"; } //创建中国人实例 var Chinese=new Person() //将其作为原型建立中国男人的实例 var ChineseMen=Object.create(Chinese); ChineseMen.gender="male"; //将其作为原型建立中国男老师的实例 var ChineseMenTeacher=Object.create(ChineseMen); ChineseMenTeacher.job="teacher"; console.log(ChineseMenTeacher.country,ChineseMenTeacher.gender,ChineseMenTeacher.job) // China Male teacher console.log(ChineseMenTeacher.__proto__) //Person{gender:"male"} console.log(ChineseMen.__proto__) //Person{country:"China"} console.log(Chinese.__proto__==Person.prototype) //true console.log(Chinese.__proto__.__proto__==Object.prototype) //true console.log(Chinese.__proto__.__proto__.__proto__) //null

我们首先建立了一个构造函数,并且将其“country”属性设置为“China”,然后由此构造函数创建了“Chinese”实例,然后以此为原型创建了ChinessMen对象,并将其gender属性设为“male”,然后以此为原型创建了ChinessMenTeacher对象,并将其job属性设为“teacher”,由此对象有原型,对象的原型还有原型,这样就生成了一条“原型链”。

原型链最底层的对象继承了上面所有层对象的属性,因此ChineseMenTeacher对象也继承了相应的gender属性以及country属性。

然后我们对对象的原型进行输出,ChineseMenTeacher对象的原型为Person{gender:“male”},即为ChineseMen,ChineseMen的对象的原型为Person{country:“China”},即为Chinese,Chinese对象的原型即为其对应构造函数的prototype属性,即Person.prototype。其原型具体为:
在这里插入图片描述
我们可以看到Chinese对象的原型有一个__proto__属性,说明其还有原型,并且其原型的__proto__属性里有一个constructor属性,为f Object(),所以Chinese.__proto__的原型对象为Object构造函数的prototype属性。具体原型如下图:
在这里插入图片描述
到了Object的prototype在不会再有原型了,其原型为null。

我们再次以图的形式来形象的说明原型链之间的关系,下图黄色的线就是原型链。
在这里插入图片描述


作者:KennyXiaoCode



原型链 JavaScript

需要 登录 后方可回复, 如果你还没有账号请 注册新账号