深入理解JavaScript构造函数与原型链:从原理到最佳实践
一、开篇:为什么需要理解原型链?
在JavaScript开发中,90%以上的"诡异"bug都与原型链机制相关。理解构造函数与原型链的运行原理,不仅能帮助我们写出更优雅的代码,还能在框架源码阅读、性能优化等场景中游刃有余。本文将通过全新视角,带你系统掌握这一核心机制。
二、构造函数:对象创建的基石
2.1 构造函数基础
function User(name) {this.name = namethis.login = function() {console.log(`${this.name} logged in`)}
}const user1 = new User('Alice')
const user2 = new User('Bob')
这种传统方式存在明显问题:每个实例都会创建新的login方法,造成内存浪费。
2.2 new操作符的魔法
当使用new调用函数时,JS引擎会执行以下步骤:
- 创建空对象
{}
- 设置原型链接:
obj.__proto__ = Constructor.prototype
- 绑定this并执行构造函数
- 自动返回新对象(除非构造函数返回对象)
三、原型对象:共享的智慧
3.1 原型方法优化
function User(name) {this.name = name
}User.prototype.login = function() {console.log(`${this.name} logged in`)
}
此时所有User实例共享同一个login方法,内存效率提升100倍(实测10,000个实例可节省约1.5MB内存)。
3.2 原型链查找机制
访问对象属性时,JS引擎会:
- 检查实例自身属性
- 沿
__proto__
链向上查找 - 直到Object.prototype为止(终点为null)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-URxwgDf1-1741881116173)(https://via.placeholder.com/600x300/EEE/000?text=Prototype+Chain+Diagram)]
四、进阶原型操作
4.1 原型继承的三种方式
// 1. 构造函数继承
function Admin(...args) {User.apply(this, args)
}// 2. 原型链继承
Admin.prototype = Object.create(User.prototype)// 3. 组合继承(最优)
function Admin(...args) {User.apply(this, args)
}
Admin.prototype = Object.create(User.prototype)
Admin.prototype.constructor = Admin
4.2 ES6 class语法糖
class User {constructor(name) {this.name = name}login() {console.log(`${this.name} logged in`)}
}class Admin extends User {constructor(name, level) {super(name)this.level = level}
}
Babel转译后的代码显示,class本质仍是基于原型链的实现。
五、性能优化实践
5.1 原型方法 vs 实例方法
方式 | 内存占用 | 访问速度 | 适用场景 |
---|---|---|---|
原型方法 | 低 | 稍慢 | 通用方法 |
实例方法 | 高 | 快 | 需要闭包/私有变量的方法 |
5.2 原型污染防护
// 冻结原型防止修改
Object.freeze(User.prototype)// 使用无原型对象
const safeObj = Object.create(null)
六、常见问题解析
6.1 原型链关系判断
// 正确方式
console.log(user1 instanceof User) // true
console.log(User.prototype.isPrototypeOf(user1)) // true// 错误方式
console.log(user1.__proto__ === User.prototype) // 不推荐直接访问__proto__
6.2 箭头函数陷阱
function User() {this.name = 'test'this.getName = () => this.name // 箭头函数没有prototype
}const u = new User()
console.log(u.hasOwnProperty('getName')) // true
七、现代开发最佳实践
- 优先使用class语法,保持代码可读性
- 复杂对象方法使用原型存储
- 避免超过3层的原型继承
- 使用组合模式代替深度继承
- 利用WeakMap实现真正私有属性
八、从框架看原型应用
- Vue组件系统:每个组件都是Vue基类的扩展
- React类组件:通过继承React.Component获得生命周期方法
- Express中间件:通过原型链实现功能扩展
九、总结与思考
理解原型链机制是成为JavaScript高手的必经之路。通过本文的学习,我们不仅掌握了原型链的运作原理,更学会了如何在现代开发中合理运用这一特性。下次当你遇到undefined is not a function
错误时,不妨先检查原型链的指向是否正确。
思考题:如何实现一个可以撤销修改的原型链系统?欢迎在评论区分享你的方案!
相关文章:
深入理解JavaScript构造函数与原型链:从原理到最佳实践
一、开篇:为什么需要理解原型链? 在JavaScript开发中,90%以上的"诡异"bug都与原型链机制相关。理解构造函数与原型链的运行原理,不仅能帮助我们写出更优雅的代码,还能在框架源码阅读、性能优化等场景中游刃…...
java每日精进 3.12 【WebSocket进阶】
基于 SpringWebSocket 进行二次封装,实现了更加简单的使用方式。例如说,WebSocket 的认证、Session 的管理、WebSocket 集群的消息广播等等。 1. 用户认证与登录用户信息传递 1.1 Token 过滤器 (TokenAuthenticationFilter) ① 在 WebSocket 连接建立…...
国家网络安全事件应急预案
目 录 1 总则 1.1 编制目的 1.2 编制依据 1.3 适用范围 1.4 事件分级 1.5 工作原则 2 组织机构与职责 2.1 领导机构与职责 2.2 办事机构与职责 2.3 各部门职责 2.4 各省(区、市)职责 3 监测与预警 3.1 预警分级 3.2 预警监测 3.3 预警研判…...
Markdown:Mermaid 画图
目录 安装基本语法流程图时序图甘特图总结 Mermaid 是一款用于生成流程图、时序图、甘特图等图表的 JavaScript 库。它可以将简单的文本描述转化为美观的图表,方便开发者进行可视化展示。 安装 Mermaid 可以直接在浏览器中使用,也可以在 Node.js 环境中…...
【视频】ffmpeg、Nginx搭建RTMP、HLS服务器
1、源码安装Nginx 1)源码下载 因为要使用Nginx的模块nginx-rtmp-module,所以要下载 nginx 和 nginx-rtmp-module 的源码。 下载地址: http://nginx.org/en/download.html https://github.com/arut/nginx-rtmp-module/tags2)解压、配置 在同一个目录中解压 nginx 和 nginx…...
时间有限,如何精确设计测试用例?5种关键方法
精确设计测试用例能够迅速识别并修复主要缺陷,确保产品质量,降低后期维护成本,并通过专注于核心功能来提升用户体验,为项目的成功奠定坚实基础。若未能精确设计测试用例,可能会导致关键功能测试不充分,使得…...
【算法】图论
⭐️个人主页:小羊 ⭐️所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 持续更新中...1、DFS2、BFSN 叉树的层序遍历二叉树的锯齿形层序遍历二叉树最大宽度 3、多源BFS腐烂的苹果 4、拓扑排序 持续更新中…...
ADQ32 5G采集卡
ADQ32是一款高端12位双通道数据采集板,针对高通量科学应用进行了优化。ADQ32具有以下特性: 一个和两个模拟输入通道包括每通道5和2.5 GSPS7GB/s的持续数据传输速率至GPU7GB/秒的持续数据传输速率两个外部触发器通用输入/输出(GPIO)开放式FPG…...
机器人领域专业名词汇总
1. 电机与驱动 电机类型 DC Motor(直流电机):通过直流电源驱动的电机。Stepper Motor(步进电机):通过脉冲信号控制旋转角度的电机。Servo Motor(伺服电机):带有反馈控制的…...
拆解 “ES 已死“ 伪命题:Agentic RAG 时代搜索引擎的终极形态
作者:来自 Elastic 李捷 xxx:“ES已死,#%#……” 我:??? 最近,某厂商发了一堆公关文章,翻来覆去地炒作 “ES 已死”,“放弃 ES”。这哪是什么正经的技术文章&…...
eNSP中路由器的CON/AUX接口、GE Combo接口、Mini USB接口、USB接口、WAN侧uplink接口、FE接口、GE接口介绍
路由器常见接口的详细介绍及其应用示例: 1. CON/AUX 接口 全称:Console/Auxiliary(控制台/辅助接口)作用: CON(Console):通过命令行界面(CLI)直接配置路由器…...
平面的四种方程及一些应用
平面的四种方程及一些应用 点法式方程一般式方程三点式方程截距式方程一些应用已知平面方程,找出平面上不共线的三个点 点法式方程 平面经过点 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) (x0,y0,z0)且法向量为 ( a , b , c ) (a,b,c) (a,b,c),则平面的点…...
记录一个SQL自动执行的html页面
在实际工作场景中,需要运用到大量SQL语句更新业务逻辑,对程序员本身,写好的sql语句执行没有多大问题(图1),但是对于普通用户来说还是有操作难度的。因此我们需要构建一个HTML页面(图2࿰…...
SpringBoot——Maven篇
Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的工具。它具有许多特性,其中一些重要的特性包括: 1. 自动配置:Spring Boot 提供了自动配置的机制,可以根据应用程序的依赖和环境自动配置应用程序的各种组件ÿ…...
数据批处理(队列方式)
数据批处理(队列方式) public class DataProcessor {private static final int THREAD_COUNT 4;private static final int QUEUE_SIZE 10;private LinkedBlockingQueue<Data> queue new LinkedBlockingQueue<>(QUEUE_SIZE);public DataP…...
从零开始搭建搜索推荐系统(五十四)多路召回之万剑归宗
聊的不止技术。跟着小帅写代码,还原和技术大牛一对一真实对话,剖析真实项目筑成的一砖一瓦,了解最新最及时的资讯信息,还可以学到日常撩妹小技巧哦,让我们开始探索主人公小帅的职场生涯吧! (PS…...
c++介绍函数指针 十
指针代表内存中地址标识符,变量,数组都是存储内存中的数据。所以可以获得它们的地址,用指针来表示这块内存。 如图输出内存中的地址。 对于一个函数来说,也是内存中存储这段数据,所以我们也可以获取函数的地址。 函数…...
redis数据库
一、redis数据库介绍 NoSQL Not Only SQL 非关系型数据库 1、关系型数据库与非关系型数据库的区别 非关系型数据库性能高、速度快、支持高并发连接 1、非关系型数据库基于内存存储数据 2、摒弃了关系型数据的约束限制 3、采用o1算法进行设计开发 2、作用 关系型数…...
关于 NoC 中数据安全传输的设计与实现的详细介绍
片上网络(Network-on-Chip,NoC)作为一种新兴的片上通信架构,解决了传统总线架构在大规模集成电路设计中面临的诸多问题。然而,随着芯片系统的复杂性和应用场景的多样化,NoC 中数据安全传输变得至关重要。以…...
OpenGL(4)着色器
文章目录 一、着色器1、什么是着色器?2、着色器类型2.1、顶点着色器(Vertex Shader)2.2、片段着色器(Fragment Shader) 3、着色器属性3.1、layout 属性3.2、in 属性3.3、out 属性3.4、总结 4、示例 前言: 在…...
PHP批量去除Bom头的方法
检查的代码: <?php$dir __DIR__; $files new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));foreach ($files as $file) {if ($file->isFile() && pathinfo($file, PATHINFO_EXTENSION) php) {$content file_get_contents(…...
51单片机的keil c51软件安装教程
Keil(C51)介绍、下载、安装与注册_keil c51-CSDN博客 参考 安装 不一定是这个大小,也可以下载别的版本KEID C51 注册 加入芯片型号 …...
JavaScript基本知识
文章目录 一、JavaScript基础1.变量(重点)1-1 定义变量及赋值1-2 变量的命名规则和命名规范判断数据类型: 2.数据类型转换2-1 其他数据类型转成数值2-2 其他数据类型转成字符串2-3 其他数据类型转成布尔 3.函数3-1函数定义阶段3-2函数调用阶段…...
导数,积分及常用公式
导数定义: 求导是数学计算中的一个计算方法,它的定义就是,当自变量的增量趋于零时,因变量的增量与自变量的增量之商的极限。在一个函数存在导数时,称这个函数可导或者可微分。可导的函数一定连续。不连续的函数一定…...
鸿蒙应用开发—ZDbUtil高效使用数据库
文章目录 介绍下载安装基本使用注解TableIdColumnOneToOne 使用方法定义实体类初始化数据库并根据被Table注解的类创建表创建表查数据插入数据删除数据清空数据 参考 介绍 ZDbUtil是一款基于SQLite的鸿蒙数据库框架,通过注解标注实体类与属性,让数据更能…...
强化学习(赵世钰版)-学习笔记(7.时序差分学习)
本章是课程算法与方法中的第四章,介绍的时序差分学习算法是基于随机近似方法设计的强化学习方法,也是model-free的方法。 时序差分算法是一种近似估计策略状态值的算法,具体的形式如下: 本质上是在当前t时刻,被访问到的…...
正则表达式入门及常用的正则表达式
正则表达式(Regular Expression,简称 Regex)是一种强大的文本处理工具,用于匹配、查找和替换字符串中的特定模式。以下是入门指南和常用正则表达式示例: 一、正则表达式入门 1. 基本语法 符号说明示例.匹配任意单个字…...
大白话如何在 Vue 项目中进行路由懒加载?
大白话如何在 Vue 项目中进行路由懒加载? 在 Vue 项目里,路由懒加载是种很实用的技术,它能让你在需要的时候再去加载对应的路由组件,而不是在项目启动时就把所有组件都加载进来,这样能加快项目的启动速度。下面就详细…...
手动实现一个RTTI系统
在 C 中,RTTI(Runtime Type Information,运行时类型信息)是一组允许程序在运行时获取对象类型信息的机制 。虽然C通过虚接口的方式提供了良好的抽象,但是对于一个复杂的系统,过于依赖抽象而忽略业务的复杂性…...
智能化水利监管:无人机视频在违章行为识别中的应用
随着我国经济社会的快速发展,水利工程建设规模不断扩大,但随之而来的违章建设行为也日益增多。传统的人工巡查方式效率低下,难以满足当前监管需求。无人机技术以其灵活性和高效性,为水利工程建设监管提供了新的解决方案。本文将探…...
力扣练习之确定两个字符串是否接近
目录 题目: 题解: 详细题解 题目: 如果可以使用以下操作从一个字符串得到另一个字符串,则认为两个字符串 接近 : 操作 1:交换任意两个 现有 字符。 例如,abcde -> aecdb 操作 2࿱…...
Word 小黑第21套
对应大猫22 设置表格为页面的80%:表布局 -属性 -表格 指定宽度80% 度量单位改成百分比 段落组 -中文版式 在表格上下方留一行空段(如果表格太大改一下样式)插入横线 边框线 (右击横线 -图片 修改样式) 段落 -取消对于…...
mingw32编译ffmpeg
ffmpeg https://gitee.com/mirrors/ffmpeg.git 使用msys2的mingw32 pacman -S mingw-w64-x86_64-toolchain compile ./confiure --enable-static --disable-shared --enable-gpl --target-oswin32 mingw32-make -j4 提示编译错误,msys2里面的路径是/d/tools/msys2…...
设计模式C++
针对一些经典的常见的场景, 给定了一些对应的解决方案,这个就叫设计模式。 设计模式的作用:使代码的可重用性高,可读性强,灵活性好,可维护性强。 设计原则: 单一职责原则:一个类只做一方面的…...
使用 Excel 实现绩效看板的自动化
引言 在日常工作中,团队的绩效监控和管理是确保项目顺利进行的重要环节。然而,面临着以下问题: 数据分散:系统中的数据难以汇总,缺乏一个宏观的团队执行情况视图。看板缺失:系统本身可能无法提供合适…...
ngx_openssl_conf_t
ngx_openssl_conf_t 定义在 src\event\ngx_event_openssl.c typedef struct {ngx_uint_t engine; /* unsigned engine:1; */ } ngx_openssl_conf_t; 1. 这个结构体的目的是存储与 OpenSSL 引擎相关的配置信息。 2. engine 字段用于标识是否启用 OpenSSL 的硬件加速引擎…...
深度学习环境配置指令大全
文章目录 环境配置官网/博客合集清华镜像站anaconda官网pytorch官网pytorch历史库官网pytorch与cuda对应版本下载博客torch与torchvision与python对应关系python与pytorch对应关系 环境相关创建环境激活环境退出环境删除环境检查环境冲突 安装相关安装requirementsconda安装con…...
Netty启动源码NioEventLoop剖析accept剖析read剖析write剖析
学习链接 NIO&Netty - 专栏 Netty核心技术十–Netty 核心源码剖析Netty核心技术九–TCP 粘包和拆包及解决方案Netty核心技术七–Google ProtobufNetty核心技术六–Netty核心模块组件Netty核心技术五–Netty高性能架构设计 聊聊Netty那些事儿 - 专栏 一文搞懂Netty发送数…...
<03.13>八股文补充知识
import java.lang.reflect.*; public class Main {public static void main(String[] args) throws Exception {// 获取 Class 对象//1. 通过类字面量Class<?> clazz Person.class;//2 通过对象实例化String str "Hello";Class<?> clazz_str str.ge…...
[HUBUCTF 2022 新生赛]messy_traffic
下载附件 看到文件类型直接用wireshark打开,对MySQL协议进行追踪流,并没有什么发现,后面对NO.437发现有用信息,http追踪流 发现**system(‘cat passwd.txt’);**这里是在打开查看passwd.txt,密码是"SignUpForHUBU…...
条款1:理解模版性别推导
目录 问题引出 情况1:ParamType是个指针或引用,但不是个万能引用。 情况2:ParamType是个万能引用 情况3:ParamType既非指针也非引用 问题引出 函数模板大致形如: template<typename T> void f(ParamType p…...
kafka连问
1,kafka多消费者指部署多个服务消费节点吗 2,多个消费节点自动组成消费组吗 3,消费者组与多消费节点关系 4,一个分区,多个消费者,可以保证有序消费吗 5,kafka如何实现顺序消费,一…...
Linux中基础开发工具详细介绍
目录 软件包管理器什么是软件包Linux软件生态 yum具体操作查看软件包安装软件卸载软件注意事项 编辑器VimLinux编辑器-vim使用vim的基本概念快速编辑的指令 编译器gcc/g背景知识gcc编译选项预处理(进行宏替换)编译(生成汇编)汇编(生成机器可识…...
浅谈时钟启动和Systemlnit函数
时钟是STM32的关键,是整个系统的心脏,时钟如何启动,时钟源如何选择,各个参数如何设置,我们从源码来简单分析一下时钟的启动函数Systemlnit()。 Systemlnit函数简介 我们先来看一下源程序的注释…...
社交软件频繁更新,UI 设计在其中扮演什么角色?
在当今数字化时代,社交软件已成为人们日常生活中不可或缺的一部分。随着科技的飞速发展和用户需求的不断变化,社交软件更新频率日益加快。在这频繁更新的背后,UI 设计扮演着至关重要的角色,它如同社交软件的 “门面担当” 与 “交…...
SQLMesh 系列教程:解锁SQLMesh的宏与变量魔法
在数据库流水线开发中,代码复用与动态配置是提升效率的核心诉求。SQLMesh以其独特的宏系统与用户定义变量机制,重新定义了SQL生成的灵活性。与传统模板引擎不同,SQLMesh的宏并非简单的字符串替换,而是基于语义理解的智能代码重构—…...
React篇之three渲染
需求:拖拽右侧面板,里面的three模型能够自适应 import { useEffect, useState, useRef } from react import ./App.css import * as THREE from three; import { GLTFLoader } from three/addons/loaders/GLTFLoader.js; import { debounce } from loda…...
PHP与前端框架的无缝集成:最佳实践与案例分析
PHP与前端框架的无缝集成:最佳实践与案例分析 在现代Web开发中,PHP作为后端语言与前端框架的集成已成为一种常见的开发模式。无论是传统的MVC架构,还是现代的SPA(单页应用),PHP与前端框架的无缝集成能够显…...
Redis内存淘汰策略
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列等场景。由于 Redis 数据存储在内存中,而内存资源有限,因此需要内存淘汰策略来管理内存的使用。Redis 提供了多种内存淘汰策略,可以根据不同的应用场景选择合适的策略。 …...
Facebook 的框架及技术栈
一、前端框架与技术 React.js 及其生态系统 核心原理与特点 React.js 是 Facebook 开源的用于构建用户界面的 JavaScript 库。它的核心概念是组件化,将用户界面拆分成一个个独立的、可复用的组件。每个组件都有自己的状态(state)和属性&#…...