【前端面经】JS-深浅拷贝
理解深浅拷贝
深浅拷贝问题的出现是由于JavaScript对不同类型的存储方式而引发的。
对于原始数据类型,它们的值是直接存储在栈内存中;
而复杂数据类型,则在栈内存中记录它的指针,而指针指向堆内存中真正的值。
所以对于原始数据类型,就没有深浅拷贝一说;而对于复杂数据类型,浅拷贝就是仅复制指针,但被复制对象改变时,新复制的对象也会跟着改变;深拷贝则是连同堆内存中的数据完全拷贝一份,新旧对象的变化互不影响。
深浅拷贝的定义
浅拷贝:
拷贝复杂类型时,仅拷贝对象的指针;当原对象改变时,拷贝对象也会跟着改变。
深拷贝:
拷贝复制类型时,拷贝对象的值;当原对象改变时,拷贝对象不会跟着改变。
深浅拷贝的实现方案
浅拷贝方案:
- 展开运算符(ES6)
- Object.assign()
- concat
- …
深拷贝:
- 手写递归
- JSON.parse(JSON.stringfy())
- 先转换成字符串,再解析回对象
- 缺点是不能处理正则表达式和函数等特殊数据类型
- 一些库封装的深拷贝方法,例如Lodash的_.cloneDeep()
手写实现
// 先写一个浅拷贝
function _deepClone(target) {let cloneRes = {};for(const key in target) {cloneRes[key] = target[key]}return cloneRes// 函数出口// if (typeof target !== 'obejct') return target
}// 2. 普通深拷贝(只考虑对象/非对象)
function _deepClone(target) {if (typeof target === 'object'){// 如果是对象,进行处理let cloneRes = {};for(const key in target) {cloneRes[key] = _deepClone(target[key])}return cloneRes} else {// 如果不是对象,直接返回return target}
}// 3.考虑数组的深拷贝
function _deepClone(target) {if (typeof target === 'object') {let cloneRes = Array.isArray(target) ? [] : {}; // 核心for (const key in target) {cloneRes[key] = _deepClone(target[key])}return cloneRes} else {return target}
}// 4. 考虑循环引用
// Q:为什么要用WeakMap替代Map?
// A:强引用和弱引用的区别,强引用只能手动释放,弱引用能够被垃圾回收机制释放,使用Map会造成内存额外消耗。
// WeakMap中的键是弱引用,Map中的键是强引用
function _deepClone(target, map=new WeakMap()) {if (typeof target === 'object') {let cloneRes = Array.isArray(target) ? [] : {}; // 核心// 防止循环调用导致的栈内存溢出if (map.get(target)) {return map.get(target)}map.set(target, cloneRes)for (const key in target) {cloneRes[key] = _deepClone(target[key], map)}return cloneRes} else {return target}
}// 5. 考虑其他数据类型
function _deepClone (target, map = new WeakMap()) {if (target === null) return nullif (target instanceof Date) return new Date(target)if (target instanceof RegExp) return new RegExp(target);if (typeof target !== 'object') return targetif (map.get(target)) return map.get(target);let cloneRes = new target.constructor()map.set(target, cloneRes)for (const key in target) {if (target.hasOwnProperty(key)) {cloneRes[key] = _deepClone(target[key], map);}}return cloneRes
}
// 6. 性能优化
// 把for..in改为普通的for循环,性能会有所提高// 测试案例
const target = {field1: 1,field2: undefined,field3: {child: 'child'},field4: [2, 4, 8]
};
const newTarget = _deepClone(target)
newTarget.field4[1] = "Child2"
console.log(target);
console.log(newTarget);
console.log(target === newTarget);
// 输出:
// {
// field1: 1,
// field2: undefined,
// field3: { child: 'child' },
// field4: [ 2, 4, 8 ]
// }
// {
// field1: 1,
// field2: undefined,
// field3: { child: 'child' },
// field4: [ 2, 'Child2', 8 ]
// }
// false
参考链接&&相关文章
前端早读课【第2810期】JavaScript 深拷贝性能分析
相关文章:
【前端面经】JS-深浅拷贝
理解深浅拷贝 深浅拷贝问题的出现是由于JavaScript对不同类型的存储方式而引发的。 对于原始数据类型,它们的值是直接存储在栈内存中; 而复杂数据类型,则在栈内存中记录它的指针,而指针指向堆内存中真正的值。 所以对于原始数据类…...
【自然语言处理】实验2布置:Word2Vec TransE案例
NLP_class 学堂在线《自然语言处理》实验课代码报告,授课老师为刘知远老师。课程链接:https://www.xuetangx.com/training/NLP080910033761/1017121?channeli.area.manual_search。 持续更新中。 所有代码为作者所写,并非最后的“标准答案…...
Redis集合底层实现原理
目录 本章重点简单动态字符串SDS集合底层实现原理zipListlistPackskipListquickListKey 与Value中元素的数量 本章重点 掌握Redis简单动态字符串了解Redis集合底层实现原理 简单动态字符串SDS SDS简介 我们Redis中无论是key还是value其数据类型都是字符串.我们Redis中的字符…...
OVS常用命令与使用总结
OVS常用命令与使用总结 说明 在平时使用ovs中,经常用到的ovs命令,参数,与举例总结,持续更新中… 进程启动 1.先准备ovs的工作目录,数据库存储路径等 mkdir -p /etc/openvswitch mkdir -p /var/run/openvswitch …...
一以贯之:从城市网络到“城市一张网”
《论语里仁》中子曰:“参乎,吾道一以贯之”。 孔子所说的“一以贯之”,逐渐成为了中国文化与哲学的重要组成部分,指明事物发展往往需要以标准化、集约化、融合化作为目标。这种智慧在数字化发展中格外重要。从云计算、大数据技术模…...
【Java校招面试】基础知识(四)——JVM
目录 前言一、基础概念二、反射三、类加载器ClassLoader四、JVM内存模型后记 前言 本篇主要介绍Java虚拟机——JVM的相关内容。 “基础知识”是本专栏的第一个部分,本篇博文是第四篇博文,如有需要,可: 点击这里,返回…...
项目管理-计算专题(三点估算、PERT估算)
基本概念 通过考虑估算中的不确定性和风险,可以提高活动持续时间估算的准确性。这个概念源自计划评审技术(PERT)。PERT使用三种估算值来界定活动持续时间的近似区间: 最可能时间(tM):基于最可能获得的资源、最可能取得的资源生产率、对资源可用时间的现…...
【华为OD机试 2023最新 】模拟商场优惠打折(C语言题解 100%)
文章目录 题目描述输入描述输出描述用例题目解析代码思路C语言题目描述 模拟商场优惠打折,有三种优惠券可以用,满减券、打折券和无门槛券。 满减券:满100减10,满200减20,满300减30,满400减40,以此类推不限制使用; 打折券:固定折扣92折,且打折之后向下取整,每次购…...
使用TrieTree(字典树)来实现敏感词过滤
使用TrieTree(字典树)来实现敏感词过滤 1. 字典树定义 字典树(TrieTree),是一种树形结构,典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串,如01字典树)。…...
USB转串口芯片CH9101U
CH9101是一个USB总线的转接芯片,实现USB转异步串口。提供了常用的MODEM联络信号,用于为计算机扩展异步串口,或者将普通的串口设备或者MCU直接升级到USB总线。 特点 全速USB设备接口,兼容USB V2.0。内置固件,仿真标准串…...
Java语言介绍
Java是一种广泛使用的计算机编程语言,由Sun Microsystems公司于1995年推出。它是一个健壮的、面向对象的、跨平台的语言,被用于开发各种应用程序和系统,包括Web应用程序、移动应用程序、桌面应用程序、游戏以及企业级系统等。 Java具有许多优…...
终于把 vue-router 运行原理讲明白了(二)!!!
一、vue-router路由变化侦测 1.1 上一遍文章中,介绍了vue-router 的install 函数的内部实现,知道了能在this中访问$router 和视图更新的机制,文章链接终于把 vue-router 运行原理讲明白了(一)!!…...
ChatGPT实现服务器体验沙箱
服务器体验沙箱 IT 人员在学习一门新技术时,第一个入门门槛通常都是"如何在本地安装并成功运行"。因此,很多技术的官网都会通过沙箱技术,提供在线试用的 playground 或者按步模拟的 tour。让爱好者先在线尝试效果是否满足预期&…...
【算法】刷题中的位运算
作者:指针不指南吗 专栏:算法篇 🐾人类做题的过程,其实是暴搜的过程🐾 文章目录 1.位运算概述2.位运算符3.位运算应用3.1整数的奇偶性判断3.2有关 2 的幂的应用3.3lowbit(x)返回x的最后一位13.4二进制数中1的个数3.5求…...
9.Java中异常处理机制是什么
Java的异常处理通过五个关键字来实现,分别是捕获异常:try,catchsfinally;声明异常:throws;抛出异常:throw 一:try,catch捕获异常二:finally回收资源三&#x…...
GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图
GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图 介绍 本教程将介绍如何使用GeoTools库在Java中将栅格数据(GeoTIFF)与矢量数据(Shapefile)叠加显示,并将结果保存为PNG格式的图片文件。我们将解析和分析 RasterDataRenderer 类,并了解其中的每个方法和对象。 准…...
nginx配置sh脚本远程执行一键安装
背景 本地多机重复操作某些shell指令,分步执行,很耗费时间, 需要远程一键部署,傻瓜化运维,更为通用安装。 即参考docker通用安装 sudo curl https://get.docker.com | sh - # sudo python3 -m pip install docker-co…...
Excel表格成绩排名全攻略,让你事半功倍!
在学校或公司中,我们经常需要对成绩进行排名。如果手动计算排名,不仅费时费力,而且容易出错。幸运的是,Microsoft Excel提供了一个简单而快速的方法来计算和显示排名。 在学校或公司中,成绩排名是一项重要的任务。使用…...
Docker 持久化存储 Bind mounts
Docker 持久化存储 Bind mounts Bind mounts 的 -v 与 --mount 区别启动容器基于bind mount挂载到容器中的非空目录只读 bind mountcompose 中使用 bind mount 官方文档:https://docs.docker.com/storage/bind-mounts/ Bind mounts 的 -v 与 --mount 区别 如果使用…...
LVS +Keepalived 高可用群集部署
一、LVSKeepalived 高可用群集 在这个高度信息化的 IT 时代,企业的生产系统、业务运营、销售和支持,以及日常管理等环节越来越依赖于计算机信息和服务,对高可用(HA)技术的应用需求不断提高,以便提供持续的…...
桶排序:分布式排序的高效实现
桶排序:分布式排序的高效实现 算法原理 核心思路 桶排序是一种分布式排序算法,其核心思想是: 将待排序的数据分到有限数量的桶里每个桶再分别进行排序(可以使用其他排序算法)最后将各个桶中的数据有序地合并起来 复杂度…...
3分钟完成Axure RP中文界面汉化:终极完整指南
3分钟完成Axure RP中文界面汉化:终极完整指南 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包,不定期更新。支持 Axure 9、Axure 10。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axu…...
开源工具Cats Blender插件:模型导入效率提升全攻略
开源工具Cats Blender插件:模型导入效率提升全攻略 【免费下载链接】cats-blender-plugin :smiley_cat: A tool designed to shorten steps needed to import and optimize models into VRChat. Compatible models are: MMD, XNALara, Mixamo, DAZ/Poser, Blender R…...
Mellanox ZTR技术解析:如何通过RTTCC实现零配置高性能RoCE网络
1. 什么是Mellanox ZTR技术? 第一次听说Mellanox ZTR(Zero Touch RoCE)技术时,我的反应和大多数人一样:"这又是什么高大上的黑科技?"但当我真正在金融交易系统里部署它之后,才发现这可…...
Vue 3 + hls.js 实战:手把手教你打造一个能‘续命’的安防监控播放器
Vue 3 hls.js 打造安防级视频流播放器的"续命"秘籍 在安防监控、智慧城市等实时视频流应用场景中,网络抖动、服务中断、页面切换等问题常常导致视频播放中断,严重影响监控效果。本文将深入探讨如何基于Vue 3和hls.js构建一个具备"续命&q…...
手把手教你用Python+AI大模型,把Yapi接口文档变成自动化测试脚本(附避坑指南)
用Python与大模型实现Yapi接口自动化测试的工程化实践 在中小型技术团队中,接口测试往往是质量保障的薄弱环节。传统手工编写测试用例的方式不仅耗时耗力,更难以应对快速迭代的开发节奏。本文将分享如何利用Python生态与AI大模型能力,将Yapi平…...
OpenClaw+Qwen3-32B双镜像方案:AI写作与发布自动化流水线
OpenClawQwen3-32B双镜像方案:AI写作与发布自动化流水线 1. 为什么需要双镜像协作? 去年冬天,当我第一次尝试用AI自动化完成技术博客的写作和发布时,遇到了一个典型困境:本地模型响应快但质量一般,云端大…...
FireRedASR-AED-L从零部署:无需Python环境,Docker镜像开箱即用指南
FireRedASR-AED-L从零部署:无需Python环境,Docker镜像开箱即用指南 你是否遇到过这样的情况?想用最新的语音识别模型,却被复杂的Python环境、版本冲突和依赖安装搞得焦头烂额。或者好不容易装好了环境,又因为音频格式…...
Pixel Dream Workshop实操手册:VAE Tiling开启前后显存占用与渲染质量对比
Pixel Dream Workshop实操手册:VAE Tiling开启前后显存占用与渲染质量对比 1. 引言 Pixel Dream Workshop(像素幻梦创意工坊)是一款基于FLUX.1-dev扩散模型的像素艺术生成工具。它采用了独特的16-bit像素风格界面设计,为创作者提…...
SEO_快速见效的页面SEO优化检查清单与方法
SEO: 快速见效的页面SEO优化检查清单与方法 在当前的互联网环境中,搜索引擎优化(SEO)已经成为了每个网站运营者必须掌握的技能。特别是在百度这样的主流搜索引擎中,优化页面的SEO不仅能提升网站的流量,还能显著增加用户…...
