当前位置: 首页 > news >正文

JS原型和原型链的理解

原型链图,图中Parent是构造函数,p1是通过Parent实例化出来的一个对象

在这里插入图片描述

前置知识

  1. js中对象和函数的关系,函数其实是对象的一种

  2. 函数、构造函数的区别,任何函数都可以作为构造函数,但是并不能将任意函数叫做构造函数,只有当一个函数通过new关键字调用的时候才可以成为构造函数

    var Parent = function(){}
    var p1 = new Parent();
    
  3. 三个属性__proto__、prototype、 constructor

    • proto、 constructor属性是对象所独有的
    • prototype属性是函数独有的
    • js中函数也是对象的一种,那么函数同样也有属性__proto__、 constructor

prototype属性

在这里插入图片描述

  • prototype 它是函数独有的属性,从图中可以看到它从一个函数指向另一个对象,代表这个对象是这个函数的原型对象,这个对象也是当前函数所创建的实例的原型对象。

  • prototype设计之初就是为了实现继承,让由特定函数创建的所有实例共享属性和方法,也可以说是让某一个构造函数实例化的所有对象可以找到公共的方法和属性。有了prototype我们不需要为每一个实例创建重复的属性方法,而是将属性方法创建在构造函数的原型对象上(prototype)。那些不需要共享的才创建在构造函数中。

  • 当我们想为通过Parent实例化的所有实例添加一个共享的属性时,
    Parent.prototype.name = "我是原型属性,所有实例都可以读取到我";

  • 这就是原型属性,当然你也可以添加原型方法。那问题来了,p1怎么知道他的原型对象上有这个方法呢,往下看

proto属性

在这里插入图片描述

  • __proto__属性是对象(包括函数)独有的。从图中可以看到__proto__属性是从一个对象指向另一个对象,即从一个对象指向该对象的原型对象(也可以理解为父对象)。显然它的含义就是告诉我们一个对象的原型对象是谁。

  • 上面说到,Parent.prototype上添加的属性和方法叫做原型属性和原型方法,该构造函数的实例都可以访问调用。那这个构造函数的原型对象上的属性和方法,怎么能和构造函数的实例联系在一起呢,就是通过__proto__属性。每个对象都有__proto__属性,该属性指向的就是该对象的原型对象
    p1.__proto__ === Parent.prototype; // true

  • __proto__通常称为隐式原型,prototype通常称为显式原型,那我们可以说一个对象的隐式原型指向了该对象的构造函数的显式原型。那么我们在显式原型上定义的属性方法,通过隐式原型传递给了构造函数的实例。这样一来实例就能很容易的访问到构造函数原型上的方法和属性了。
    我们之前也说过__proto__属性是对象(包括函数)独有的,那么Parent.prototype也是对象,那它有隐式原型么?又指向谁?
    Parent.prototype.__proto__ === Object.prototype; //true

  • 可以看到,构造函数的原型对象上的隐式原型对象指向了Object的原型对象。那么Parent的原型对象就继承了Object的原型对象。由此我们可以验证一个结论,万物继承自Object.prototype。这也就是为什么我们可以实例化一个对象,并且可以调用该对象上没有的属性和方法了。如:
    //我们并没有在Parent中定义任何方法属性,但是我们可以调用 p1.toString();//hasOwnProperty 等等的一些方法

  • 我们可以调用很多我们没有定义的方法,这些方法是哪来的呢?现在引出原型链的概念,当我们调用p1.toString()的时候,先在p1对象本身寻找,没有找到则通过p1.__proto__找到了原型对象Parent.prototype,也没有找到,又通过Parent.prototype.__proto__找到了上一层原型对象Object.prototype。在这一层找到了toString方法。返回该方法供p1使用

  • 当然如果找到Object.prototype上也没找到,就在Object.prototype.__proto__中寻找,但是Object.prototype.proto === null所以就返回undefined。这就是为什么当访问对象中一个不存在的属性时,返回undefined了

constructor属性

在这里插入图片描述

  • constructor是对象才有的属性,从图中看到它是从一个对象指向一个函数的。指向的函数就是该对象的构造函数。每个对象都有构造函数,好比我们上面的代码p1就是一个对象,那p1的构造函数是谁呢?我们打印一下。
    console.log(p1.constructor); // ƒ Parent(){}
  • 通过输出结果看到,很显然是Parent函数。我们有说过函数也是对象,那Parent函数是不是也有构造函数呢?显然是有的。再次打印下
    console.log(Parent.constructor); // ƒ Function() { [native code] }
  • 通过输出看到Parent函数的构造函数是Function(),这点也不奇怪,因为我们每次定义函数其实都是调用了new Function(),下面两种效果是一样的
    var fn1 = new Function('msg','alert(msg)');
    function fn1(msg){alert(msg);
    }
    
  • 那么我们再回来看下,再次打印Function.constructor
    console.log(Function.constructor); // ƒ Function() { [native code] }
  • 可以看到Function函数的构造函数就是本身了,那我们也就可以说Function是所有函数的根构造函数。
  • 到这里我们已经对constructor属性有了一个初步的认识,它的作用是从一个对象指向一个函数,这个函数就是该对象的构造函数。通过栗子我们可以看到,p1的constructor属性指向了Parent,那么Parent就是p1的构造函数。同样Parent的constructor属性指向了Function,那么Function就是Parent的构造函数,然后又验证了Function就是根构造函数

参考:https://segmentfault.com/a/1190000021232132 # 巴斯光年

相关文章:

JS原型和原型链的理解

原型链图,图中Parent是构造函数,p1是通过Parent实例化出来的一个对象 前置知识 js中对象和函数的关系,函数其实是对象的一种 函数、构造函数的区别,任何函数都可以作为构造函数,但是并不能将任意函数叫做构造函数&…...

力扣题单(小白友好)

力扣题单 算法小白自用题单,目前对于一些简单的数据结构感觉掌握的还可以,但是力扣很多题还是需要看题解,不够熟练;故整理了一份题单,用于巩固练习; 网上确实有很多对于算法分类讲解的网站,but:有一丢丢选择困难症,每天不知道该刷什么题,再加上网站对于一类题一般就有十几道题目…...

王道c语言ch11-单链表的新建、插入、删除例题

王道c语言ch11-单链表的新建、插入、删除例题 #include <stdio.h> #include <stdlib.h> #define END 33typedef int ElemType;typedef struct LNote {ElemType data;struct LNote *next; } LNote, *LinkList;//头插法 void list_head_insert(LinkList &L) {El…...

蓝桥杯刷题--python-23

2.危险系数 - 蓝桥云课 (lanqiao.cn) n, m map(int, input().split()) map_ [[] for i in range(n 1)] used [0 for i in range(n 1)] used_ [0 for i in range(n 1)] cnt 0 res [] for _ in range(m):u, v map(int, input().split())map_[u].append(v)map_[v].appen…...

蓝桥杯刷题--python-24

0地图 - 蓝桥云课 (lanqiao.cn) from math import * import sys from functools import lru_cache # sys.setrecursionlimit(100000) n, m, k map(int, input().split()) a [input() for i in range(n)] dr [(0, 1), (1, 0)] cnt 0 lru_cache(maxsizeNone) def dfs(x, y, …...

面向对象(C# )

面向对象&#xff08;C# &#xff09; 文章目录 面向对象&#xff08;C# &#xff09;ref 和 out传值调用和引用调用ref 和 out 的使用ref 和 out 的区别 结构体垃圾回收GC封装成员属性索引器静态成员静态类静态构造函数拓展方法运算符重载内部类和分布类 继承里氏替换继承中的…...

Lombok:@Cleanup资源释放利器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、Cleanup介绍 二、使用示例 三、价值阐述 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、Cleanup介绍 Cleanup可以自动管理输…...

IoT 物联网场景中 LoRa + 蓝牙Bluetooth 室内场馆高精定位技术全面解析

基于LoRa蓝牙的室内场景定位技术&#xff0c;蓝牙主要负责位置服务&#xff0c;LoRa主要负责数据传输。 01 LoRa和蓝牙技术 LoRa全称 “Long Rang”&#xff0c;是一种成熟的基于扩频技术的低功耗、超长距离的LPWAN无线通信技术。LoRa主要采用的是窄带扩频技术&#xff0c;抗干…...

SpringCloudAlibaba系列之Seata实战

目录 环境准备 1.下载seata安装包 2.修改配置文件 3.准备seata所需配置文件 4.初始化seata所需数据库 5.运行seata 服务准备 分布式事务测试 环境准备 1.下载seata安装包 Seata-Server下载 | Apache Seata 本地环境我们选择稳定版的二进制下载。 下载之后解压到指定目录…...

蓝桥杯day5刷题日记-分巧克力-天干地支-求和

P8647 [蓝桥杯 2017 省 AB] 分巧克力 思路&#xff1a;二分查找 #include <iostream> using namespace std; int n,k; int h[100010],w[100010];bool check(int x) {int sum0;for(int i0;i<n;i){sum(h[i]/x)*(w[i]/x);if(sum>k) return true;}return false; }int…...

C++ ostringstream用法详解

std::ostringstream 是 C 标准库中的一个输出字符串流类&#xff0c;它可以用于将各种数据类型转换为字符串&#xff0c;并且支持格式控制和字符串拼接操作。 目录 1. 头文件 2. 基本用法 3. 将各种数据类型转换为字符串 4. 格式控制 5. 清空和重置 6. 拼接字符串 1. 头…...

并发编程所需的底层基础

一、计算机运行的底层原理 1.多级层次的存储结构 ①:辅存 固态盘不是主要的应用对象&#xff0c;因为固态盘的使用次数是有限的&#xff0c;无法支撑高并发场景 磁盘存储的最基本原理是电生磁。 磁盘的磁道里边有很多的磁颗粒&#xff0c;磁颗粒上边有一层薄膜为了防止磁点氧…...

各种小功能

目录 Python在指定目录创建多个相似命名的文件夹 Python 在指定目录创建多个相似命名的文件夹...

vue前端解析jwt

vue前端解析jwt 我们可以用在线解析看解析的结果&#xff1a;https://www.lddgo.net/encrypt/jwt-decrypt 但是如果在前端需要解析token&#xff0c;拿到其中的权限信息&#xff0c;可以这样解决。 在线的&#xff1a; 完美解决&#xff1a; 代码&#xff1a; function par…...

【Flutter 面试题】Flutter如何进行本地存储和缓存数据?

【Flutter 面试题】Flutter如何进行本地存储和缓存数据&#xff1f; 文章目录 写在前面口述回答补充说明实际案例完整代码示例运行结果详细说明 写在前面 &#x1f64b; 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff0c;GitChat专栏作者&#xff0c;阿里云…...

Docker 笔记(八)--Dockerfile

目录 1. 背景2. 参考3. 原文3.1 Dockerfile 支持的指令3.2 Dockerfile格式3.3 Parser指令syntaxescape 3.4 环境变量替换3.5 docker构建忽略文件3.6 Shell 和 exec 格式Exec 格式Shell 格式使用不同的 shell 3.7 FROM指令了解ARG和FROM如何交互 3.8 RUN指令RUN指令缓存失效RUN …...

C语言每日一题06

一、题目 二、解析 void main &#xff08;&#xff09; { char c1&#xff0c;c2&#xff1b; int a1&#xff0c;a2&#xff1b; c1 getchar &#xff08;&#xff09;&#xff1b;//读取第一个输入&#xff0c;c11 scanf &#xff08;“%3d”&#xff0c;&a1&#xff…...

spring redis 工具类

1、引入jar <!-- redis 缓存操作 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2、代码 /*** 缓存基本的对象&#xff0c;Integer、String、…...

SpringBoot3整合Elasticsearch8.x之全面保姆级教程

整合ES 环境准备 安装配置ES&#xff1a;https://blog.csdn.net/qq_50864152/article/details/136724528安装配置Kibana&#xff1a;https://blog.csdn.net/qq_50864152/article/details/136727707新建项目&#xff1a;新建名为web的SpringBoot3项目 elasticsearch-java 公…...

微信小程序云开发教程——墨刀原型工具入门(表单组件)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…...

机器学习结合基因无关通路映射:从临床数据挖掘新药靶点

1. 项目概述&#xff1a;当机器学习遇见代谢通路&#xff0c;如何从数据中“挖”出新药靶点&#xff1f;在生物医学研究的前沿&#xff0c;我们正面临一个核心矛盾&#xff1a;一方面&#xff0c;我们拥有海量的临床数据&#xff0c;比如血糖、血压、BMI等指标&#xff1b;另一…...

SwitchyOmega+Burp无感抓包实战:解决HTTPS拦截与流量路由难题

1. 为什么“无感抓包”是BurpSuite日常使用的分水岭刚接触Web安全测试的朋友常有个错觉&#xff1a;装上Burp Suite&#xff0c;配好代理&#xff0c;打开浏览器&#xff0c;点几下网页——流量就该自动进来了。结果现实是&#xff1a;首页打不开、登录态丢失、HTTPS报错满屏、…...

告别网盘客户端!用Alist+RaiDrive把百度云盘变成电脑本地文件夹(保姆级图文教程)

用AlistRaiDrive实现网盘本地化管理的终极方案 你是否厌倦了电脑上安装多个网盘客户端&#xff0c;不仅占用系统资源&#xff0c;操作还繁琐割裂&#xff1f;每次上传下载文件都要在不同客户端间切换&#xff0c;效率低下。现在&#xff0c;通过Alist和RaiDrive的组合&#xf…...

BLE四大广播模式详解:可连接/不可连接/定向/周期广播

一、前言在低功耗蓝牙&#xff08;BLE&#xff09;开发中&#xff0c;广播&#xff08;Advertising&#xff09;是设备发现、连接建立、数据广播、设备重连的核心基石&#xff0c;所有BLE交互流程均始于广播报文的收发。不同于传统经典蓝牙&#xff0c;BLE所有广播行为标准化、…...

Java数组工具类实战:设计不可实例化的静态工具类

实现一个工具类 MathUtils&#xff0c;满足以下要求&#xff1a; 1. 所有方法均为静态&#xff0c;且该类不能从外部实例化&#xff08;提示&#xff1a;使用私有构造器&#xff09;。 2. 提供三个静态方法&#xff1a;- maxArray(int[] arr)&#xff1a;返回较大值&#xff1b…...

Simulink中Repeating Sequence锯齿波显示恒为0解决方案

锯齿波设置如图1时&#xff0c;其示波器显示恒为0&#xff08;如图2&#xff09;。图1图2于是新建模型&#xff0c;只添加Repeating Sequence模块&#xff0c;采用原始设置发现可以正常输出锯齿波&#xff0c;于是调整时间参数&#xff0c;发现当时间设置为≥[0 0.06]时可以正常…...

销售怎么通过各种方法获取电话号码

第一种就是那个用爬虫电话号码&#xff0c;然后再打电话给客户。第二种是在别人的挪车电话看车挪车电话&#xff0c;然后再打电话找客户。第三就是。扫楼一顿顿的扫&#xff0c;第四就是这个那种商店&#xff0c;一个个的去问陌拜地推一个个的问店子要不要贷款&#xff0c;去问…...

终极艾尔登法环帧率解锁指南:轻松突破60FPS限制

终极艾尔登法环帧率解锁指南&#xff1a;轻松突破60FPS限制 【免费下载链接】EldenRingFpsUnlockAndMore A small utility to remove frame rate limit, change FOV, add widescreen support and more for Elden Ring 项目地址: https://gitcode.com/gh_mirrors/el/EldenRing…...

在Hermes Agent项目中接入Taotoken作为自定义模型供应商

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在Hermes Agent项目中接入Taotoken作为自定义模型供应商 基础教程类&#xff0c;针对使用Hermes Agent框架的开发者&#xff0c;详…...

flameshow性能优化技巧:如何快速定位Go程序中的CPU热点

flameshow性能优化技巧&#xff1a;如何快速定位Go程序中的CPU热点 【免费下载链接】flameshow A terminal Flamegraph viewer. 项目地址: https://gitcode.com/gh_mirrors/fl/flameshow &#x1f525; 想要快速定位Go程序中的性能瓶颈吗&#xff1f;flameshow是一个强大…...