看完这篇,再也不害怕别人问我什么是原型了
myzbx 2025-08-31 06:15 24 浏览
本文转载自微信公众号「不知名宝藏程序媛」,作者小土豆 。转载本文请联系不知名宝藏程序媛公众号。
前言
原型、原型链应该是被大多数前端er说烂的词,但是应该还有很多人不能完整的解释这两个内容,当然也包括我自己。
最早一篇原型链文章写于2019年07月,那个时候也是费了老大劲才理解到了七八成,到现在基本上忘的差不多了。时隔两年,兴趣所向重新开始复盘一下原型和原型链的内容。
JavaScript中的对象
在JavaScript中,对象被称为是一系列属性的集合。
创建对象的方式也有很多种,最常见的一种就是双花括号的形式:
var obj = {}; 
obj.name = '小土豆'; 
obj.age  = 18; 这种方式实际上是下面这种方式的语法糖:
var obj = new Object(); 
obj.name = '小土豆'; 
obj.age  = 18; 除此之外,在JavaScript中也可以通过构造函数自定义对象。
function Cat(){} 
var catMimi = new Cat();  // 自定义对象 如果一个函数使用new关键字调用,那么这个函数就可以称为是构造函数,否则就是普通函数。
什么是原型
一句话简单总结原型:原型是一个对象。
在后面的总结中,原型可能会被描述为原型对象,其等价于原型
原型从哪里来?原型这个对象存在于哪里,需要通过代码去创建吗?
我们说对象是一系列属性的集合,那原型这个对象包含什么属性呢?
如何操作和使用原型?
接下来我们一个一个问题去探究。
原型从哪里来
JavaScript会为所有的函数创建一个原型。
function Cat(){} 上面的代码中我们创建了一个Cat函数,那这个Cat函数就有一个原型,用代码表示就是:Cat.prototype。
同样我们创建一个函数Fn1,函数Fn1就有一个原型,用代码表示就是Fn1.prototype。
函数名称的大写和小写本质上没有任何区别
原型包含哪些属性
前面我们说过以下这两点:
原型是一个对象
对象是一系列属性的集合
那原型都包含哪些属性呢?
前面我们已经知道原型用代码表示就是:functionName.prototype,那我们在代码中console.log一下。
function Cat(){} 
console.log("Cat.prototype:"); 
console.log(Cat.prototype); 
 
function Dog(){} 
console.log("Dog.prototype:"); 
console.log(Dog.prototype); Firefox浏览器中的输出结果如下:
可以看到函数的原型默认有两个属性:constructor和 。
其中,函数原型的constructor属性指向函数本身。
函数原型的 属性称为隐式原型,后面我们会分出一节单独介绍隐式原型。
如何操作和使用原型
正常我们操作一个普通对象的方式是下面这样的:
function Cat(){} 
console.log("Cat.prototype:"); 
console.log(Cat.prototype); 
 
function Dog(){} 
console.log("Dog.prototype:"); 
console.log(Dog.prototype); 原型既然也是一个对象,所以操作原型的方式和上述的方式相同。
function Cat(){} 
Cat.prototype.type = 'cat'; 
Cat.prototype.color = 'White'; 
Cat.prototype.sayInfo = function(){ 
    console.log(this.type + ' is ' + this.color); 
} 此时再次打印Cat.prototype就能看到我们添加到原型上的属性:
访问原型对象上的方法和属性:
以上这些操作原型的方法,对于真正的项目开发并没有什么参考价值,不过不用着急,后面我们会详细讲解
隐式原型
前面我们在总结函数的原型对象时提到过隐式原型。
那实际上,JavaScript会为所有的对象创建叫隐式原型的属性。我们一直说原型是一个对象,所以在上面的截图中,原型也有一个隐式原型属性。
隐式原型的代码表示
隐式原型
是对象的私有属性,在代码中可以这样访问:obj.__proto__。
obj.__proto__这种写法是非标准的,一些低版本的浏览器并不支持这样的写法
我们在浏览器的控制台中实际访问一下:
从打印的结果可以看到隐式原型也是一个对象,那隐式原型这个对象里面又包含什么属性呢?下面我们一起来看看。
隐式原型存在的意义
首先我们写一个简单的示例:
function Cat(){} 
var catMimi = new Cat(); 
var catJuju = new Cat(); 在上面这段代码中,我们创建了一个Cat函数,并且通过new关键字创建了以Cat为构造函数的两个实例对象catMimi和catJuju。
接下来我们在浏览器的console工具中看看这两个实例对象的隐式原型都包含了那些属性。
可以看到,catMimi.__proto__和catJuju._proto__的结果貌似是一样的,而且眼尖的同学应该也发现了这个打印结果似乎和前面一节【原型包含那些属性】中打印的Cat.prototype是一样的。
那话不多说,我们用==运算符判断一下即可:
可以看到所有的判断结果均为true。
由于对象catMimi、catJuJu都是由Cat函数创建出来的实例,所以总结出来结论就是:对象的隐式原型__proto__指向创建该对象的函数的原型对象。
原型链:原型和隐式原型存在的意义
前面我们总结了原型、隐式原型的概念以及如何使用代码操作原型和隐式原型,总的看来原型和隐式原型好像也没有特别厉害的地方,它们到底有什么用呢?
所有的实例对象共享原型上定义的属性和方法
我们来看下面这样一个示例:
function Cat(name, age){ 
    this.type = 'RagdollCat';  //布偶猫 
    this.eyes = 2; 
    this.name = name; 
    this.age = age; 
    this.sayInfo = function(){ 
        console.log(this.type + ' ' + this.name + ' is ' + this.age + ' years old'); 
    } 
} 在这个示例中,我们创建了一个Cat函数,同时Cat函数有五个属性:type、eyes、name、age、sayInfo,其中type和eyes属性已经有了初始值,而name、age通过参数传递并赋值;sayInfo对应是一个函数,打印出type、name和age的值。
接着我们创建Cat的两个实例对象catMimi、catJuju,并传入不同的name和age参数。
var catMimi = new Cat('Mimi', 1); 
var catJuju = new Cat('Juju', 2); 控制台查看一下我们创建的对象:
可以看到这两个对象有着相同的属性,由于type、eyes是在Cat函数创建时已经有了固定的初始值,所以这两个属性值是相同的;sayInfo函数也都是相同的功能,打印出一些属性的信息;只有name、age是通过参数传递的,各自的值不相同。除此之外呢,catMimi和catJuju是两个不同的对象,两者的属性值互相独立,修改其中任意一个的属性值并不会影响另外一个对象的属性值。
假如之后我们有更多这样的对象,JavaScript还是会为每一个对象创建相同的属性,而这些所有的对象都拥有着相同的type、eyes属性值和相同功能的sayInfo函数。这无疑造成了内存浪费,那这个时候我们就可以将这些属性定义到函数的原型对象上:
function Cat(name, age){ 
    this.name = name; 
    this.age = age; 
} 
 
Cat.prototype.type = 'RagdollCat';    //布偶猫 
Cat.prototype.eyes = 2; 
Cat.prototype.sayInfo = function(){ 
    console.log(this.type + ' ' + this.name + ' is ' + this.age + ' years old'); 
} 
var catMimi = new Cat('Mimi', 1); 
var catJuju = new Cat('Juju', 2); 然后我们再来看看这两个对象:
可以看到这两个对象现在只包含了两个属性,就是Cat构造函数内容内部定义的两个属性:name、age。
接着我们在去访问对象上的type、eyes和sayInfo:
我们的实例对象还是可以正常访问到属性,方法也打印出来正确的信息。那到底是怎么访问到的呢?
原型链
在上一个示例代码中,我们将一些属性和方法定义到函数的原型上,最后使用该函数创建出来的实例对象可以正常访问原型上定义的属性和方法,这是怎么做到的呢?
前面我们说过:对象的隐式原型指向创建该对象的函数的原型对象,所以当实例对象中没有某个属性时,JavaScript就会沿着该实例对象的隐式原型去查找,这便是我们所说的原型链。
那既然是链,我们想到的应该是一个连着一个的东西,所以应该不仅仅是当前实例对象的隐式原型指向创建该对象的函数的原型对象,所以我们在对catMimi对象做点操作:
在上面的操作,我们调用了catMimi的hasOwnProperty方法,很明显我们并没有为这个对象定义该方法,那这个方法从哪里来呢?
答案依然是原型链:
- 调用catMimi.hasOwnProperty()方法
 - 在实例对象catMimi中查找属性,发现没有该属性
 - 去catMimi.__proto__中查找,因为catMimi.__proto__=Cat.prototype(实例对象的隐式原型指向创建该实例的函数的原型),也就是在Cat.prototype中查找hasOwnProperty属性,很明显Cat.prototype也没有该属性
 - 于是继续沿着Cat.prototype.__proto__查找,又因为Cat.prototype.__proto__ = Object.prototype(我们一直在强调原型是一个对象,既然是对象,就是由Object函数创建的,所以Cat.prototype的隐式原型指向Object函数的原型)
 
我们打印一下Object.prototype的是否包含hasOwnProperty属性:
可以看到,Object.prototype中存在hasOwnProperty属性,所以catMimi.hasOwnPrototype实际上调用的是
Object.prototype.hasOwnProperty。
总结
本篇文章到此基本就基本结束了,相信大家应该对原型和原型链有了一定的了解。最后呢,我们在对本篇文章做一个总结。
原文链接:
https://mp.weixin.qq.com/s/59p32Xe03YCGhP2uTBjTUg
相关推荐
- 如何设计一个优秀的电子商务产品详情页
 - 
        
加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...
 
- 怎么在JS中使用Ajax进行异步请求?
 - 
        
大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...
 
- 中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革
 - 
        
前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...
 
- 前端监控 SDK 开发分享_前端监控系统 开源
 - 
        
一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...
 
- Ajax 会被 fetch 取代吗?Axios 怎么办?
 - 
        
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...
 
- 前端面试题《AJAX》_前端面试ajax考点汇总
 - 
        
1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...
 
- Ajax 详细介绍_ajax
 - 
        
1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...
 
- 6款可替代dreamweaver的工具_替代powerdesigner的工具
 - 
        
dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...
 
- 我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊
 - 
        
接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...
 
- 福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光
 - 
        
时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...
 
- 2021年超详细的java学习路线总结—纯干货分享
 - 
        
本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...
 
- 不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!
 - 
        
Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...
 
- 2025 年 Python 爬虫四大前沿技术:从异步到 AI
 - 
        
作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...
 
- 最贱超级英雄《死侍》来了!_死侍超燃
 - 
        
死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...
 
- 停止javascript的ajax请求,取消axios请求,取消reactfetch请求
 - 
        
一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...
 
- 一周热门
 
- 最近发表
 
- 标签列表
 - 
- HTML 简介 (30)
 - HTML 响应式设计 (31)
 - HTML URL 编码 (32)
 - HTML Web 服务器 (31)
 - HTML 表单属性 (32)
 - HTML 音频 (31)
 - HTML5 支持 (33)
 - HTML API (36)
 - HTML 总结 (32)
 - HTML 全局属性 (32)
 - HTML 事件 (31)
 - HTML 画布 (32)
 - HTTP 方法 (30)
 - 键盘快捷键 (30)
 - CSS 语法 (35)
 - CSS 轮廓宽度 (31)
 - CSS 谷歌字体 (33)
 - CSS 链接 (31)
 - CSS 定位 (31)
 - CSS 图片库 (32)
 - CSS 图像精灵 (31)
 - SVG 文本 (32)
 - 时钟启动 (33)
 - HTML 游戏 (34)
 - JS Loop For (32)
 
 
