再说原型链

news2024/10/5 17:40:57

关于原型链,已经被无数次的提起,每次回顾都有新的理解,今天我们再来说说原型链。
我们知道,每一个javascript对象(除了null)在被创建的时候都会与另一个对象关联起来,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。
好,问题来了,我们需要原型链来做些什么呐?

原型的作用

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.eat = function() {
    console.log(age + "岁的" + name + "在吃饭。");
  }
}

let p1 = new Person("小夏", 18);
let p2 = new Person("小夏", 18);

console.log(p1.eat === p2.eat); // false

呐,其实结果我们也预想到了,每次创建对象都会重新开辟出新的堆,所以p1和p2指向的地址是不一样的,以前的讨论基本到此为止,那么今天问一下,有没有什么办法,可以让他们指向同一个地址,节省内存呢?我们需要开辟出一块公共的区域,这个概念,就是我们所说的原型对象。

function Person(name) {
  this.name = name;
}

// 通过构造函数的 Person 的 prototype 属性找到 Person 的原型对象
Person.prototype.eat = function() {
  console.log("吃饭");
}

let p1 = new Person("小夏", 18);
let p2 = new Person("小夏", 18);

console.log(p1.eat === p2.eat); // true

上述就是我们通过原型实现对eat的公共管理,所有通过Person实例化的对象,都会继承eat属性。
关于显式原型prototype和隐式原型_proto_的概念,这边不再过多赘述,如果不太了解,请移步小夏的另一篇原型和原型链了解后再来看本篇。

普通对象和函数对象

对象可以分为两类,普通对象和函数对象。
普通对象
除了函数对象以外所有的对象都是普通对象,包括new 函数对象()产生的实例,普通对象没有prototype,也就没有继承和原型链这一说了。
函数对象
包括两种:

  • 由function创造出来的函数:
function f1(){}
var f2=function(){}
var f3=new Function('x','console.log(x)');
//以上都是函数对象
  • 系统内置的函数对象:Function、Object、Array、String、Number,还有正则对象RegExp、Date对象等等,它们在js中的构造源码都是function xxx(){[native code]},Function其实不仅让我们用于构造函数,它也充当了函数对象的构造器,比如Object对象的构造源码其实是Function Object(){[native code]},甚至它也是自己的构造器.
String._proto_===Function.prototype
//true
Object._proto_===Function.prototype
//true
Function._proto_===Function.prototype
//true

js中原型等式,对象._proto_===构造器.prototype,由此可以看出他们之间的关系。
问题来了,我们知道所有对象继承自Object对象,但是我们刚刚又说Object对象继承自Function,嗯???是不是有点矛盾了?Object和Function是相互继承的吗?从一定程度上来讲,可以这么理解。

Object和Function

一切对象都最终继承自Object对象,Object对象直接继承自根源对象null
我们可以发现,在原型链分析中,所有对象的原型链的最终都是=>Object.prototype=>null。一切对象都包含有Object的原型方法,Object的原型方法包括了toStringvalueOfhasOwnProperty等等,在js中不管是普通对象还是函数对象都拥有这些方法。
这条定律放在Function对象上依然成立,只不过Function的原型链稍微复杂了一点,它比较特别的地方就是它的构造器是自己,即直接继承了自己,最终继承于Object,什么玩意?怎么这么怪,对,就是这么怪,Function继承了他自己,最终继承了Object。

Function._proto_===Function.prototype
//true
Function.prototype._proto_===Object.prototype
//true
Object.prototype._proto_===null
//true

练习

var F = function() {

};
Object.prototype.a = function() {
    console.log('a()');
};
Function.prototype.b = function() {
    console.log('b()');
};
var f = new F();
f.a(); 
f.b(); 
F.a(); 
F.b();

//a()
//报错
//a()
//b()

根据分析可以画出下面的关系图:
在这里插入图片描述
可以看到在函数对象F的原型链中包含Function的原型方法和Object的原型方法,但是普通对象没有Function的原型方法,只有Object的原型方法。所以f.b()会报错。

拓展

new做了什么?
new关键字会进行如下操作:
1.创建一个空的简单js对象 (var a={})
2.为新创建的对象添加属性_proto_,将该属性链接到构造函数的原型对象(a._proto_=Foo.prototype)
3.将新创建的对象作为this的上下文(var b=Foo.call(a))
4.如果该函数没有返回对象,则返回this.(return b)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/134419.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++进阶】二叉搜索树

文章目录二叉搜索树概念二叉搜索树操作二叉搜索树的实现每个节点的结构插入查找删除二叉搜索树的所有代码(包括测试)版本一版本二test.cpp二叉搜索树概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空&a…

Linux环境下gdb程序调试

目录gdb介绍进入gdb调试环境指令学习l(list)指令b(break)指令info b指令d指令r(run)指令n(next)指令s(step)指令c(continue)指令bt(breaktrace)指令finish指令p(print)指令display指令undisplay指令until指令disable命令enable命令这篇文章将会介绍gdb以及一些常用的gdb调试指令…

3.移动端百分比布局练习-京东首页

访问地址 https://youthddup.gitee.io/myproject/ 1、项目目录结构 2、注意 (1)设置视口标签以及引入初始化样式 (2)二倍精灵图缩放 先把精灵图等比缩放原来的一半 然后再测精灵图位置 代码里background-size置为原来的一半 &a…

typescript 数组操作

使用变量来存储值会带来以下限制: 变量本质上是标量。换言之,一个变量声明变量声明一次只能包含一个。这意味着在程序中存储n个值需要n个变量声明。因此,当需要存储更大的值集合时,使用变量是不可行的。 程序中的变量以随机顺序分…

当下一场数字化的浪潮,正在各行各业深刻上演着

一场数字化的浪潮,正在各行各业深刻上演着。在零售领域,亦不例外。以往,提及零售,我们更多地想到的是,各式各样的电商平台,我们看到的是,各式各样的电商模式;现在,提及零…

测试用例设计-淘宝购物车

测试人员和开发人员产生争执了怎么办? ① 先检查自身,是否BUG描述不清楚 ② 站在用户的角度考虑问题 ③ BUG定级要有理有据 ④ 提高自身的技术能力和业务水平,最好同时提出解决方案。 ⑤ 开发人员不接受时,不要争吵,可…

YOLOv5更换骨干网络之 PP-LCNet

论文地址:https://arxiv.org/abs/2109.15099 代码地址:https://github.com/ngnquan/PP-LCNet 我们提出了一种基于MKLDNN加速策略的轻量级CPU网络,名为PP LCNet,它提高了轻量级模型在多个任务上的性能。本文列出了在延迟几乎不变的…

YOLOv5更换骨干网络之 EfficientNet-B0

论文地址:https://arxiv.org/abs/1905.11946 代码地址:https://githeb.com/TensorFlow/tpu/tree/master/Models/Offical/Efficientnet 卷积神经网络(ConvNet)通常是在固定的资源预算下开发的,如果有更多的资源可用,则…

如何从macOS ventura降级到 macOS Monterey?这两大方法可以帮到你

苹果发布了macOS 13 Ventura的正式版系统,增加了许多实用性的功能,大家纷纷下载更新最新版本的系统。但根据许多已安装ventura的用户反馈,这个版本的MacOS系统还不够成熟,应该有不少bug还没有修复过来,从而求助小编分享…

c#入门-泛型约束

泛型约束 使用泛型时会假设泛型占位符是任何类型。 但因为它被假设是任何类型,所以使用起来有很大的限制。只有所有类型都有的功能,他才能用。 为了满足所有的可能类型,可用的操作非常少。 为此我们可以为泛型占位符添加约束。虽然会让能兼…

大型项目迭代流程

一、回顾目标 总目标: 年底上线完成100% 结果: 年底上线并开量验证过成功,完成率100% 阶段目标A: 10月底项目全流程开发完成,并提测出票前流程 结果:10月21日项目开发完成100%,10月25日前…

基于残差神经网络的交通标志识别算法研究与应用实现

问题: 从图像中识别交通标志对于自动驾驶至关重要。要想实现自动驾驶,车辆必须了解并遵守所有交通规则。当前,特斯拉、谷歌、梅赛德斯-奔驰、丰田、福特、奥迪等许多大公司都在研究自动驾驶。因此,为了实现这项技术的准确性&…

pandas的series创建和pandans的dataFrame创建

一:series和读取外部数据 1.1pandas的series的了解 1.1.1 为什么要学习pandas numpy能够帮我们处理处理数值型数据,但是这还不够。很多时候,我们的数据除了数值之外,还有字符串,还有时间序列等 比如:我们通…

显式利用用户画像的多兴趣建模

显式利用用户画像的多兴趣建模 目前在多兴趣建模中,用户侧的特征包括用户基础画像特征(年龄、性别、地域等)、用户在当前场景的静态兴趣画像特征(短期兴趣画像、长期兴趣画像)、交互的历史正向行为序列特征&#xff0…

【Javassist】快速入门系列13 使用Javassist获取注解

系列文章目录 01 在方法体的开头或结尾插入代码 02 使用Javassist实现方法执行时间统计 03 使用Javassist实现方法异常处理 04 使用Javassist更改整个方法体 05 当有指定方法调用时替换方法调用的内容 06 当有构造方法调用时替换方法调用的内容 07 当检测到字段被访问时使用语…

MySQL性能优化三 一条SQL在MySQL中执行的过程

一 MySQL的内部组件结构 大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。 1.1 service层 主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学…

Easy-Captcha验证码 生成以及校验(简单易懂)

目录说明pom引入详解参数类使用easy-captcha 中提供了下面几种类源码说明Captcha使用验证图解源码测试GitHub说明 Java图形验证码&#xff0c;支持gif、中文、算术等类型&#xff0c;可用于Java Web、JavaSE等项目 pom引入 <dependency><groupId>com.github.whvc…

【C++】 bitset(位图)的使用

目录 一、bitset的基本介绍 1. 位图的概念 2. 位图的应用 二、biset的基本使用 1. bitset的成员函数 2. 基本使用介绍 1. 定义方式 2. 成员函数的使用 一、bitset的基本介绍 1. 位图的概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数…

win系统一台电脑安装两个不同版本的mysql教程

1.mysql下载zip包&#xff08;地址&#xff09;MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压在你的电脑上&#xff08;不要再C盘和带中文的路径&#xff09; data和my.ini是没有的。 3.创建my.ini文件 创建记事本改变后缀名就可以 …

【5G RRC】小区搜索(Cell Search)和系统捕获(System Acquisition)流程

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…