【写在前面】辞旧迎新的春季佳节,在这里博主先祝各位看官新的一年赚钱多多,知识满满,年后谈到面试, 好多人在面试的时候就倒在原型链知识点上面,主要原因还是基本功不够扎实,针对以前的知识我也计划在2023年进行一个梳理与总结,希望能够给大家带来一个全新的理解与认识,希望这篇文章能终结您的原型链知识盲区。
文章目录
- 1、什么是原型链
- 1.1原型是啥?
- 1.2 prototype 和 __proto__ 的区别与作用
- A、存在体的区别
- B、继承的作用
- C、prototype作用又是体现在哪?
1、什么是原型链
1.1原型是啥?
说到原型我们先谈对象吧,简而言之:原型存在于对象,没有对象别和我谈原型!
原型简单来说就是:对象的内置[[Prototype]]属性;
复杂来说就是:每个构造函数内部都会存在一个prototype属性,这个属性的值才是对象,该对象包括了构造函数所有实例所共享的属性和方法,当我们通过构造函数去创建一个对象的时候,这个对象就会有一个指针,这个指针会指向构造函数的prototype的值,其实我们将这个指向prototype的指针称之为原型;
结合实例讲解:
//对象函数(构造函数)
function duixiang() {
this.sex = "女";//设置对象的性别
}
其中你在控制台尝试输出构造函数的prototype属性:
不难发现,其还包括了__proto__ 这个属性,那么prototype 和 proto 究竟有什么区别和联系呢?
1.2 prototype 和 proto 的区别与作用
A、存在体的区别
首先prototype是函数所有的,实例对象是没有这个属性的,函数就是function;
然而__proto__不只是在函数Function中存在,在对象object中也存在;
B、继承的作用
对继承概念不熟悉的可以先了解一下继承概念再来看看哈,接触过java的应该都知道java是通过类和类之间实现继承的,但是JavaScript没有类,有对象,是故继承只能通过对象与对象之间来实现继承。
那么我先基于对象的概念写一个实例让大家更加快速接受js中的继承。
古时候有个富商家有四个千金去相亲,富商说,你们每个人都要写出自己的要求;
大小姐要求是:年龄在18到45岁之间的;
二小姐要求是:身高得150到180之间的;
三小姐要求是:只要孝顺、阳光就行;
四小姐却迟迟不能下笔,说这能不能我把三位姐姐的要求全拿过来啊,我要求都得满足。
富商就说:你还没学继承呢,怎么能做这种事情,于是乎找到博主我帮忙了,下面我就给这个富商罗列了一下原型继承的代码;
//相亲条件1的大小姐,只有年龄的限制
let tj1 = { age: "年龄在18-45岁" };
//相亲条件2的二小姐,只有身高的限制
let tj2 = { height: "身高在150cm-180cm" };
//相亲条件3的三小姐,只有品质的限制
let tj3 = { quality: "性格得孝顺,阳光" };
//相亲条件4的四小姐,啥都没想好
let tj4 = {};
//博主的努力下
tj4.__proto__ = tj1;
console.log("四小姐的要求:" + tj4.age);
console.log("四小姐的要求:" + tj4.height);
console.log("四小姐的要求:" + tj4.quality);
//输出
//四小姐的要求:年龄在18-45岁
//四小姐的要求:undefined
//四小姐的要求:undefined
tj4.__proto__ = tj2;
console.log("四小姐的要求:" + tj4.age);
console.log("四小姐的要求:" + tj4.height);
console.log("四小姐的要求:" + tj4.quality);
//输出
//四小姐的要求:undefined
//四小姐的要求:身高在150cm-180cm
//四小姐的要求:undefined
// 【结论】重新赋值会不覆盖
tj2.__proto__ = tj1;
console.log("四小姐的要求:" + tj4.age);
console.log("四小姐的要求:" + tj4.height);
console.log("四小姐的要求:" + tj4.quality);
//输出
//四小姐的要求:年龄在18-45岁
//四小姐的要求:身高在150cm-180cm
//四小姐的要求:undefined
// 【结论】直接修改他指向的tj2的原型就可以让他也拥有,这就是继承的概念
tj1.__proto__ = tj3;
console.log("四小姐的要求:" + tj4.age);
console.log("四小姐的要求:" + tj4.height);
console.log("四小姐的要求:" + tj4.quality);
//输出
//四小姐的要求:年龄在18-45岁
//四小姐的要求:身高在150cm-180cm
//四小姐的要求:性格得孝顺,阳光
// 【结论】其实这个就形成了一条链了,tj4指向tj2,tj2指向tj1,tj1指向tj3,这样的一条原型链使得tj4拥有tj1/tj2/tj3的三个条件
看到这里。
富商直呼:你真乃神人耶,龄几何,可婚配?
我笑而不语…大家可以在评论区留下你们的神评哈;
C、prototype作用又是体现在哪?
不免会有居心叵测之人在问,你一直在用__proto__说事,那么能不能给我唠唠prototype这个玩意究竟干了些啥,具体作用又怎么体现出来的?
这个时候我就要踩一脚__proto__了,这个其实不是官方定义的标准属性,所以在把Function当做构造函数使用的时候,需要借助prototype属性来模拟类与类之间的继承模式。
当然这个主要是针对函数来说的,首先刚才我们new了一个函数对象,那么我们去想一想new的对象类型是object,但是赋值的是一个函数function类型,下面我将new的过程给大家描述一下子哈;
//对象函数(构造函数)
function duixiang() {
this.sex = "女";//设置对象的性别
}
var xqdx = new duixiang("男");
第一步:执行duixiang 函数,duixiang函数会在xqdx的作用域(作用域后面会有专文介绍)下被执行,其中里面的this就是对象实例xqdx,从而xqdx对象就会拥有性别属性,默认为女,传男也没用;
第二步:继承函数体内属性和方法的原理其实是xqdx.__proto__指向了duixiang.prototype,这就是构造函数的精髓,从而才有属性和方法的继承。
总结一下:
__proto__是真正用来查找原型链去获取方法的对象。
prototype是在用new创建对象时用来构建__proto__的对象;
所以说,针对构造函数的属性继承,没有prototype的话,__proto__屁都不是;