JS 原型与原型链图解:彻底搞懂的终极指南

前言

 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步!

 🍅 个人主页:南木元元

 在JavaScript中,原型和原型链是非常重要的知识点,只有理解了它们,才能更好地理解js。


目录

构造函数

什么是原型

原型对象和构造函数关系

原型链

显式与隐式原型

__proto__与[[Prototype]]

原型链的概念

Object.getPrototypeOf()方法

hasOwnProperty() 方法

结语


构造函数

创建对象有两种方式:一种是最常见的对象字面量,一种就是通过构造函数来创建。

1.对象字面量

// 对象字面量
let person = {name: "南木元元",age: 22,species: "人类",greet: function() {console.log("Hello!");}
};

2.构造函数

// 构造函数创建对象
function Person(name, age) {this.name = name;this.age = age;this.species = '人类';this.greet = function() {console.log("Hello!");};
}
let person1 = new Person("南木元元", 22);

构造函数和普通函数本质上没什么区别,只不过使用了new关键字创建对象的函数,被叫做了构造函数。构造函数的首字母一般是大写,用以区分普通函数。任何函数只要使用 new 操作符调用就是构造函数,而不使用 new 操作符调用的函数就是普通函数。

// 作为构造函数
let person1 = new Person("南木元元", 22);
person1.greet() //Hello!// 作为函数调用
Person("yuanyuan", 18)
window.greet() //Hello!

什么是原型

 《javascript高级程序设计》中对原型的描述:

每个函数都会创建一个 prototype 属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。

简单来讲,原型就是一个对象,可以实现对象的属性和方法的继承

原型对象和构造函数关系

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向一个对象,这个对象就是此函数的原型对象。

当函数经过new调用时,这个函数就成为了构造函数,返回一个新的实例对象。

这个实例对象有一个__proto__属性,指向构造函数的原型对象。

每个原型对象上都有个constructor属性,指向它的构造函数。

原型对象有什么用呢?最主要的作用就是用来存放实例对象的公有属性和方法。

在上面例子中,species属性和greet方法对于所有people实例来说都一样,放在构造函数里,那每创建一个实例,就会重复创建一次相同的属性和方法,显得有些浪费。这时候,如果把这些公有的属性和方法放在原型对象里共享,就会好很多。

function Person(name, age) {this.name = name;this.age = age;
}// 定义在原型对象上
Person.prototype.species = '人类';
Person.prototype.greet = function () {console.log("Hello");
}let person1 = new Person('南木元元', 22);
let person2 = new Person('yuanyuan', 18);console.log(person1.species); // 人类 
console.log(person2.species); // 人类person1.greet(); // Hello
person2.greet(); // Hello

为什么实例对象person1和person2中可以访问构造函数Person的原型对象上的方法呢?看上图可以知道,是通过__proto__ 这个属性去访问构造函数的原型对象。

有时候,我们会用person1.constructor查看实例对象的构造函数:

console.log(person1.constructor); // Person()

这个constructor是原型对象上的属性,但实例对象也可以使用,原因就是上面所说的。那如果原型对象上也没有找到想要的属性呢?这就要说到原型链了。

原型链

讲原型链之前,我们需要先了解几个概念。

显式与隐式原型

  • 显式原型就是利用prototype属性查找原型,prototype属性是函数独有的属性。
  • 隐式原型是利用__proto__属性查找原型,这个属性是所有对象都有的属性。

隐式原型__proto__ 的属性值指向它的构造函数的显式原型prototype属性值:

console.log(person1.__proto__ === Person.prototype); // true
console.log(person2.__proto__ === Person.prototype); // true

__proto__与[[Prototype]]

[[Prototype]]用于标识对象的原型。我们来打印一下实例对象person1:

console.log(person1)

你会发现,[[Prototype]]其实就是实例对象person1的原型对象,它的值与person1.__proto__是一样的,通过__proto__可以暴露一个对象内部的原型[[Prototype]]的值。对于使用对象字面量创建的对象,该值是Object.prototype。对于使用数组字面量创建的对象,该值是Array.prototype。对于函数,该值是Function.prototype。

原型链的概念

JavaScript中所有对象都会通过 __proto__ 属性指向自己的原型对象,这个原型对象又会有自己的原型,直到指向Object对象为止,这样就形成了一个链条一样的结构,即原型链。当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型链上找这个属性,直到找到对应属性或到达原型链的末尾。

  • 原型链的终点是什么?

原型链的终点是null。原型链上的所有原型都是对象,所有的对象最终都是由 Object 构造的。可以在控制台通过Object.prototype.__proto__ 来打印原型链的终点。

Object.getPrototypeOf()方法

__proto__ 属性并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但不推荐使用该属性,我们可以使用 Object.getPrototypeOf 方法来获取实例对象的原型,然后再来为原型添加方法/属性。

hasOwnProperty() 方法

使用hasOwnProperty() 方法获得对象非原型链上的属性。

有时候,我们想要判断对象自身中是否具有指定的属性,而不是从原型中继承来的属性,这时可以使用hasOwnProperty() 方法。

function iterate(obj){var res = [];for(var key in obj){if(obj.hasOwnProperty(key)){res.push(key+': '+obj[key]);}}return res;
} 

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~ 

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

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

相关文章

2.2.填充和步幅

我们已经知道,卷积的输出形式取决于输入形式和卷积核的形式。 ​ 此外还有其他因素会影响输出的大小。假设以下情景: 有时,在应用了连续的卷积之后,我们最终得到的输出远小于输入大小。这是由于卷积核的宽度和高度通常大于1所导致…

驱动框架——CMSIS第一部分 RTE驱动框架介绍

一、介绍CMISIS 什么是CMSIS(cortex microcontrol software interface standard一种软件标准接口),官网地址:https://arm-software.github.io/CMSIS_6/latest/General/index.html 包含的core、driver、RTOS、dsp、nn等部分&…

如何评价《系统之美》这本书

系统的总体大于部分之和,因而:一万个图书管理员也无法取代一个搜索引擎 一万个图书管理员简单的拼凑在一起构不成一个系统,而搜索引擎却是个可以不断完善的系统。生物学中对于系统的定义是:“系统是能够完成一种或者几种生理功能…

Linux系统编程:自定义协议(序列化和反序列化)

1. 协议 在之前我们谈到,协议就是一种"约定",socket api接口,在读写数据时,都是按照"字符串"的方式来发送接收的,那么我们要传输一些"结构化"数据时怎么办呢?,比如说一个结构…

前端-04-VScode敲击键盘有键入音效,怎么关闭

目录 问题解决办法 问题 今天正在VScode敲项目,不知道是按了什么快捷键还是什么的,敲击键盘有声音,超级烦人啊!!于是我上网查了一下,应该是开启了VScode的键入音效,下面是关闭键入音效的办法。…

kafka---消息日志详解

一、Log Flush Policy(log flush 策略) 1、设置内存中保留日志的个数,当达到这个数量的时候,内存中的数据会被强制刷到disk中 log.flush.interval.messages10000 2、设置内存中保留日志的时间,当达到这个时间的时候&am…

DP刷题(1500-1700)

1.区间DP&#xff1a;https://www.acwing.com/problem/content/323/ 比较容易想到区间DP,转换一下均方差定义用记忆化搜索就可以了。 下面是AC代码&#xff1a; #include<bits/stdc.h> using namespace std; const int N 16; int n, m 8; int s[N][N]; double f[N][…

现在进行时的被动语态:为什么是 “being“?

在学习英语语法时&#xff0c;曾对现在进行时的被动语态感到困惑&#xff0c;特别是为什么要用“being”这个词。 1. 进行时态&#xff08;Present Continuous Tense&#xff09; 进行时态用于表示动作正在发生。其结构是&#xff1a;主语 am/is/are 动词的现在分词&#xf…

分布式服务框架zookeeper+消息队列kafka

一、zookeeper概述 zookeeper是一个分布式服务框架&#xff0c;它主要是用来解决分布式应用中经常遇到的一些数据管理问题&#xff0c;如&#xff1a;命名服务&#xff0c;状态同步&#xff0c;配置中心&#xff0c;集群管理等。 在分布式环境下&#xff0c;经常需要对应用/服…

云计算数据中心(三)

目录 四、自动化管理&#xff08;一&#xff09;自动化管理的特征&#xff08;二&#xff09;自动化管理实现阶段&#xff08;三&#xff09;Facebook自动化管理 五、容灾备份&#xff08;一&#xff09;容灾系统的等级标准&#xff08;二&#xff09;容灾备份的关键技术&#…

Oracle19.24发布,打补丁到19.24

一. 19.24发布 2024年7月16日 19c&#xff0c;19.24补丁发布 文档编号19202407.9&#xff0c;文档编码规则&#xff1a; 19&#xff08;版本号&#xff09;2024&#xff08;年份&#xff09;07&#xff08;当季的第一个月01/04/07/10&#xff09;.9 一般每个季度的首月中16…

02-Spring Core中的设计模式分析

Spring Core中的设计模式分析 1. 单例模式 (Singleton Pattern) 源码分析&#xff1a; 在Spring框架中&#xff0c;Bean默认是单例的。这意味着在整个Spring IoC容器中&#xff0c;只有一个Bean实例。Spring通过DefaultSingletonBeanRegistry来实现单例模式。 public class…

Android Launcher3桌面图标样式修改(添加圆角)

1.源码类&#xff1a;LauncherActivityCachingLogic.java /** Copyright (C) 2018 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You…

js修改hash的方法

关键&#xff1a; window.onhashchange (event) > {// do something }hash变化包括 js修改hash手动修改url的hash浏览器前进、后退 js修改hash: location.href "#user";在vue-router等路由组件中如何实现history模式呢&#xff1f; 关键函数&#xff1a;hi…

【学习笔记】Redis学习笔记——第14章 客户端

第14章 服务器 14.1 命令请求的执行过程 14.1.1 发送命令请求 客户端将发送的命令准换成协议格式然后发送给服务器 14.1.2 读取命令请求 1>保存命令至客户端状态输入缓冲区 2>提取命令参数及参数个数保存至客户端状态的argv与argc字段中 3>获取命令执行器并执行命…

Flink CDC 同步表至Paimon 写数据流程,write算子和commit算子。

Flink CDC 同步表至Paimon 写数据流程,write算子和commit算子。(未吃透版) 流程图 一般基本flink cdc 任务同步数据至paimon表时包含3个算子,source、write、global commit。 source端一般是flink connector实现的连接源端进行获取数据的过程,本文探究的是 source算子获…

Haproxy服务

目录 一.haproxy介绍 1.主要特点和功能 2.haproxy 调度算法 3.haproxy 与nginx 和lvs的区别 二.安装 haproxy 服务 1. yum安装 2.第三方rpm 安装 3.编译安装haproxy 三.配置文件详解 1.官方地址配置文件官方帮助文档 2.HAProxy 的配置文件haproxy.cfg由两大部分组成&…

Synchronized升级到重量级锁会发生什么?

我们从网上看到很多&#xff0c;升级到重量锁的时候不会降级&#xff0c;再来线程都是重量级锁 今天我们来实验一把真的是这样的吗 1.首选导入Java对象内存布局的工具库&#xff1a; <dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-…

【moyu】河北省职工职业技能大赛决赛

[32m [33mMOYU [32m[0m 工作不算争取价值&#xff0c;是劳动换取酬劳&#xff1b; 工作的时候偷闲才是为自己争取价值。 [32m[0m****************************************************** ******************* 让我摸个鱼吧&#xff01; ******************* *****************…

二叉树---最大二叉树

题目&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums…