一文搞懂原型和原型链

简介: 一文搞懂原型和原型链

在了解原型和原型链之前首先得明确它俩是什么东西:

原型:prototype

又称显示原型

1、原型是一个普通对象

2、只有构造函数才具备该属性

3、公有属性可操作

隐式原型:__proto__

1、只有对象(普通对象、函数对象)具备

2、私有的对象属性,不可操作

有了上面的概念之后,我们再来探讨一下什么是原型和原型链。


原型(显示原型) : prototype


我们定义一个字符串变量的时候,该字符串本身是不具备任何方法的,但是可以调用字符串方法。

let str = 'hello'  // new String()
console.log(str);
console.log(str.length);

其实我们在定义一个字符串变量的时候,隐式的实例化了new String()这个构造函数,所以我们才可以使用字符串方法。

console.log(new String());

这个length就是String的原型方法ptototype,字符串本身有没有这个方法不重要,字符串的原型上有个方法就可以了。

原型的本质是一个普通对象,所以我们可以利用对象.属性的方式调用方法。

如果我们用字符串调用一个DCodes(),该方法在字符串属性上没有并不存在,调用该方法会报错。

我们给String的原型添加一个DCodes方法,字符串就可以调用该方法了。

String.prototype.DCodes = function(){
       console.log('你好DCodes');
}
str.DCodes() // 你好DCodes

利用原型可以干什么呢?上面也说了,构造函数才具备原型,我们创建一个构造函数,可以通过实例化这个构造函数来调用原型方法和原型属性。

// 构造函数
function Person(){
         this.name = '东方不败'
}
let per = new Person()
console.log(per);

原型的本质是一个对象,那么给Person这个原型添加一个方法

function Person(){
         this.name = '东方不败'
}
Person.prototype.sum = function(a,b){return a + b}
let per = new Person()
console.log(per);
console.log(per.sum(1,2));

构造函数记录了当前原型对象产生的归属,原型是基于那个构造函数构建的,那么constructor指向的就是那个构造函数,这里的constructor指向的就是Person()函数。


__proto__隐式原型

隐式原型只有对象(普通对象、函数对象)才具备,并且隐式原型是一个私有的对象属性,不可操作。

上面也提到过,我们定义了一个字符串,实际上是隐式的new String()String()的原型上有length,所以字符串可以调用length方法,显示原型prototype是构造函数才具备的,普通对象是没有的,那么普通对象是怎么调用构造函数的原型方法的呢?答案就是普通对象具有隐式原型,隐式原型全等于显示原型

let hello = 'hello'
console.log(hello.__proto__ === String.prototype);  // true

也就是说,普通对象的隐式原型__proto__等于构造函数的显示原型prototype,普通对象就可以调用构造函数的原型方法。

谷歌浏览器中,隐式原型__proto__的写法为: [[Prototype]]

到这里就构成了原型链,用字符串调用字符串方法的时候,字符串会在__proto__寻找对应的字符串方法,__proto__等于prototype,也就是String()构造函数,如果String()的构造函数没有该方法,那么String()会继续向上寻找,原型prototype是一个对象,那么对象就会有隐式原型__proto__String()的隐式原型__proto__Object(),然后会在Object()的原型prototype上寻找,如果Object()的原型prototype上不存在该属性,那么就会通过隐式原型__proto__继续向上寻找,直到找到对应的方法为止,如果没有找到,那么就会报错,该方法不存在。(这一段需要好好理解)

这样向上寻找,最终总会有尽头,万物的原型终点是谁呢?

字符串、数组、构造函数的原型最终都会指向Object,而Object的原型指向的是null

console.log(Object.prototype);
• 1

最后我们来看一下prototype、__proto__之间的关系:

__proto__ === prototype 
prototype == {}
{}.__proto__ == Object.prototype
......
目录
打赏
0
0
0
0
4
分享
相关文章
Vue封装组件并发布到npm仓库
前言 使用Vue框架进行开发,组件封装是一个很常规的操作。一个封装好的组件可以在项目的任意地方使用,甚至我们可以直接从npm仓库下载别人封装好的组件来进行使用,比如iview、element-ui这一类的组件库。但是每个公司的业务场景可能不同,开发人员还是得必须封装自己得组件,如果换了一个项目,那么我们就只能复制组件代码到新的项目里面去了,这样稍显麻烦,其实我们可以将组建上传到npm仓库,要用的时候可以直接从npm安装使用。 总结下来有两点好处: 方面使用,任何项目无缝衔接。 可作为开源项目,积累经验。
809 0
Vue封装组件并发布到npm仓库
打破文本边界:如何进行多模态RAG评估
一般的检索增强生成(RAG,Retrieval-Augmented Generation)方法主要依赖于文本数据,常常忽略了图像中的丰富信息。那么应该如何解决呢?本文带你了解一下这个模型。
打破文本边界:如何进行多模态RAG评估
数据库死锁的解决方案有哪些?
【10月更文挑战第28天】数据库死锁是数据库管理中的一个常见问题
373 71
Content type ‘text/plain;charset=UTF-8‘ not supported,这里要把测试文件转为json格式
Content type ‘text/plain;charset=UTF-8‘ not supported,这里要把测试文件转为json格式
|
6月前
不要再责怪你的UI设计师为什么没有用rp?ps?figma?sketch?xd?如何免费转换非在线工具收费转换-本文将教会你常规ui设计源文件格式相互之间如何转换并且保持矢量图和标注注释问题-优雅草央千澈
不要再责怪你的UI设计师为什么没有用rp?ps?figma?sketch?xd?如何免费转换非在线工具收费转换-本文将教会你常规ui设计源文件格式相互之间如何转换并且保持矢量图和标注注释问题-优雅草央千澈
156 1
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。高级技巧包括内存检查、性能分析和符号调试。通过实践案例学习如何有效定位和解决问题,同时注意保持耐心、合理利用工具、记录过程并避免过度调试,以提高编程能力和开发效率。
192 1
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
190 0
2024 Mysql基础与进阶操作系列之MySQL触发器详解(20)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
MySQL触发器基础等具体操作详解步骤;精典图示-举例说明、注意点及常见报错问题所对应的解决方法IKUN和1原们你这要是学不会我直接退出江湖;好吧!!!
【Web 前端】ES6新增的内容有哪些?
【5月更文挑战第1天】【Web 前端】ES6新增的内容有哪些?
【Web 前端】ES6新增的内容有哪些?
如何减少React中无关组件的重渲染
你是否同我一样,总是会遇到一些莫名其妙的渲染问题,有时为了解决bug,需要耗费相当气力来debug呢?快来一起学习下react re-render 这些小技巧吧,或许能帮你减少组件树中无关组件的重渲染及重挂载,可以提升性能,同时也能提高用户体验哟。 案例代码:https://github.com/buzingar/re-render-demos
2486 5
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问