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

【面试题】马上金九银十了,简历该准备起来了,面试题你准备好了吗 ?浅谈 JS 浅拷贝和深拷贝

代码展示

let obj_old = {name: 'Tom',age: 15,favorite: {food: 'bread',drink: 'milk'}
}
let obj_new = {...obj_old}
console.log(obj_old === obj_new)  // false
console.log(obj_old.name === obj_new.name)  // true
console.log(obj_old.favorite === obj_new.favorite)  // true

3. Array.prototype.concat()

语法:arr.concat(value0, /* … ,*/ valueN)

注:如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝。

代码展示

let arr_old = [1, 2, {name: 'Tom'}]
let arr_new = arr_old.concat()
console.log(arr_old === arr_new)  // false
console.log(arr_old.name === arr_new.name)  // true

4. Array.prototype.slice()

语法:arr.slice(begin, end)

注:如果省略了 beginend 参数,则 slice 会返回调用此方法的现存数组的一个浅拷贝。

代码展示

let arr_old = [1, 2, {name: 'Tom'}]
let arr_new = arr_old.slice()
console.log(arr_old === arr_new)  // false
console.log(arr_old.name === arr_new.name)  // true

🌄深拷贝

接下来说深拷贝

深拷贝就是在堆内存中开辟一个新的空间存放新对象,拷贝原对象的所有属性,拷贝前后两个对象互不影响

深拷贝的新旧对象不共享内存

这时我们去修改新对象中的任意层级的任意属性值,都不会对原对象产生影响,原对象依然保持不变

举个栗子🌰

let obj_old = {name: 'Tom',age: 15,hobby: ['eat', 'game'],favorite: {food: 'bread',drink: {dname: 'milk',color: 'white',},}
}
let obj_new = _.cloneDeep(obj_old)
console.log(obj_old)
console.log(obj_new)
console.log(obj_old.name === obj_new.name)
console.log(obj_old.favorite === obj_new.favorite)
console.log(obj_old.favorite.drink === obj_new.favorite.drink)

这里我们使用了lodash工具库提供的_.cloneDeep深拷贝方法,来看一下新旧对象的对比

可以看见新旧对象所有属性及属性值完全相同

那再来细节对比一下,看看拷贝后对象的地址是否相同

obj_old.name === obj_new.name为true,这个是基本数据类型,完全相同,没有问题

obj_old.favorite === obj_new.favorite,这里为false,到这里就和浅拷贝不同了,浅拷贝到这一层的时候,对象属性的地址是相同的,而深拷贝是完全拷贝出一个新的对象,所以不管是哪一层,对象属性的地址都是不同的

obj_old.favorite.drink === obj_new.favorite.drink为false,再往深一层仍然是false,即地址不相同

那再来修改一下属性值,看看前后对比

obj_new.name = 'Jerry'
obj_new.hobby[0] = 'sing'
obj_new.favorite.food = 'cheese'

修改属性值之后,新旧对象是互不影响的

🏷️深拷贝的方法

那么现在就来罗列几个深拷贝的方法

1. 递归实现

使用递归实现原对象每一层的拷贝,当遇到基本数据类型时,直接拷贝,遇到引用数据类型时,递归拷贝它的每个属性

代码展示

const obj_old = {name: 'Tom',age: 15,hobby: ['eat', 'game'],favorite: {food: 'bread',drink: {dname: 'milk',color: 'white',},}
}
const obj_new = {}function deepClone(newObj, oldObj){for (const key in oldObj) {if (oldObj[key] instanceof Object) {newObj[key] = {}deepClone(newObj[key], oldObj[key])} else if (oldObj[key] instanceof Array) {newObj[key] = []deepClone(newObj[key], oldObj[key])} else {newObj[key] = oldObj[key]}}
}deepClone(obj_new, obj_old)console.log(obj_old)
console.log(obj_new)
console.log(obj_old.name === obj_new.name)
console.log(obj_old.favorite === obj_new.favorite)
console.log(obj_old.favorite.drink === obj_new.favorite.drink)

测试结果

2. lodash工具包

点这里去lodash的中文文档

引入成功后,我们直接使用lodash提供给我们的函数_.cloneDeep就行

代码展示

let obj_old = {name: 'Tom',age: 15,hobby: ['eat', 'game'],favorite: {food: 'bread',drink: {dname: 'milk',color: 'white',},}
}
let obj_new = _.cloneDeep(obj_old)console.log(obj_old)
console.log(obj_new)
console.log(obj_old.name === obj_new.name)
console.log(obj_old.favorite === obj_new.favorite)
console.log(obj_old.favorite.drink === obj_new.favorite.drink)

测试结果

3. JSON.parse(JSON.stringify(obj))

JSON.stringify() 将JSON格式的对象转为字符串

JSON.parse() 将JSON格式的字符串转为对象

代码展示

const obj_old = {name: 'Tom',age: 15,hobby: ['eat', 'game'],favorite: {food: 'bread',drink: {dname: 'milk',color: 'white',},}
}
const obj_new = JSON.parse(JSON.stringify(obj_old))console.log(obj_old)
console.log(obj_new)
console.log(obj_old.name === obj_new.name)
console.log(obj_old.favorite === obj_new.favorite)
console.log(obj_old.favorite.drink === obj_new.favorite.drink)

测试结果

❣️虽然这个方法最简单,代码行数最少,但是它也有一定的缺陷:

  1. 拷贝对象的值中如果有‘函数’,‘undefined’,‘symbol’ JSON.stringify()序列化后,键值对丢失
  2. 拷贝RegExp会变成空对象{}
  3. 对象中含有‘NaN’,‘Infinity’会变成null
  4. 拷贝Date会变成字符串

🏝️结语

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

相关文章:

【面试题】马上金九银十了,简历该准备起来了,面试题你准备好了吗 ?浅谈 JS 浅拷贝和深拷贝

代码展示 let obj_old {name: Tom,age: 15,favorite: {food: bread,drink: milk} } let obj_new {...obj_old} console.log(obj_old obj_new) // false console.log(obj_old.name obj_new.name) // true console.log(obj_old.favorite obj_new.favorite) // true3. Ar…...

最新OPPO 真我手机 一加手机 使用adb命令永久关闭系统更新教程

使用adb命令永久关闭系统更新 一、先了解手机系统二、Android 11 以下使用adb 命令永久关闭系统更新1、adb 官方下载2、小白开启 USB 调试模式教程(熟手跳过)三、Android 12 以上使用adb 命令永久关闭系统更新什么您还是不会弄!赞赏我&#x…...

OnlyOffice:现代办公的最佳选择

目录 安装 使用 评价 对比(与WPS) 总结 在当今的数字化办公时代,选择一款功能全面且易于使用的办公软件至关重要。OnlyOffice作为一款现代化的办公软件,凭借其强大的功能和友好的用户体验,逐渐成为了众多企业和个…...

【收藏】2024年必备相图数据库资源集锦!

在材料化工领域,相图不仅仅是一个简单的图表,它是一个强大的工具,为材料科学家和工程师提供了深入理解材料行为的窗口。从选择合金元素及其比例的初步阶段,到后续的加工方法选择和热处理工艺的确定,相图都扮演着至关重…...

Zookeeper 二、Zookeeper环境搭建

Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式 单机模式:Zookeeper只运行在一台服务器上,适合测试环境集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”…...

Web3 学习

之前学习 web3,走了不少弯路,最近看到了 hackquest,重新刷了一遍以太坊基础,感觉非常nice,而且完全免费,有需要的可以试试,链接hackquest.io。...

Grafana+Prometheus(InfluxDB)+Jmeter使用Nginx代理搭建可视化性能测试监控平台

前言 在这篇博客文章中,将分享JMeter > Prometheus(InfluxDB) > Grafana的集成,以及Nginx端口反向代理各服务的端口。 背景 在JMeter插件库中,有一些后端监听器可供Kafka、ElasticSearch和Azure使用。默认情况下,JMeter支…...

web学习笔记(六十六)项目总结

目录 1. Suspense标签 2.发布订阅者模式 3.pinia的使用 4.在请求过来的数据添数据 5.设置token和取token 6. 实现触底加载 7.导航守卫判断登录状态。 1. Suspense标签 Suspense主要用于用于处理异步组件加载和数据获取。,使用这个标签可以允许你在组件等待数…...

红队内网攻防渗透:内网渗透之内网对抗:横向移动篇域控系统提权NetLogonADCSPACKDC永恒之蓝CVE漏洞

红队内网攻防渗透 1. 内网横向移动1.1 横向移动-域控提权-CVE-2020-1472 NetLogon1.2 横向移动-域控提权-CVE-2021-422871.3 横向移动-域控提权-CVE-2022-269231.4 横向移动-系统漏洞-CVE-2017-01461.5 横向移动-域控提权-CVE-2014-63241. 内网横向移动 1、横向移动-域控提权-…...

VMware Workstation安装Windows Server2019系统详细操作步骤

虚拟机版本 VMware Workstation 16 Prp 16.2.5 build-20904516 实现操作 创建虚拟机 创建新的虚拟机 自定义->下一步 默认即可,下一步 稍后安装操作系统->下一步 按照图下所示选择好系统->下一步 设置好虚拟机名称和位置->下一步 默认即可&#xff0…...

HTML5【新特性总结】

HTML5【新特性总结】 HTML5 的新增特性主要是针对于以前的不足,增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题,基本是 IE9 以上版本的浏览器才支持,如果不考虑兼容性问题,可以大量使用这些新特性。…...

【面试题】面试官:判断图是否有环?_数据结构复试问题 有向图是否有环

type: NODE;name: string;[x: string]: any; }; [x: string]: any;}; export type Data Node | Edge; 复制代码 * 测试数据如下const data: Data[] [ { id: ‘1’, data: { type: ‘NODE’, name: ‘节点1’ } }, { id: ‘2’, data: { type: ‘NODE’, name: ‘节点2’ } },…...

办理北京公司注册地址异常变更要求和流程

在北京注册公司时选择注册地址是非常重要的一环,注册地址不仅体现在营业执照上,在网上也有公示信息,一般选用的是商用地址和商住两用地址,在公司经营过程中,因为经营需要变更注册地址,也要依法变更&#xf…...

当你在浏览器输入一个地址

你在浏览器中输出了一个地址,回车后,一直到显示页面,中间经历了哪些过程 ? 1. 用户输入 URL 并按下回车 用户在浏览器的地址栏中输入一个 URL(例如 http://example.com)并按下回车键。 2. DNS 解析 浏览…...

JSP基础知识概述

目录 JSP一、什么是JSP1.1 概念1.2 创建JSP1.3 JSP编写Java代码1.4 JSP实现原理 二、JSP与HTML集成2.1 普通脚本2.2 声明脚本2.3 输出脚本2.4 JSP指令2.5 动作标签 三、内置对象3.1 四大域对象 JSP 一、什么是JSP 1.1 概念 简化的Servlet设计,在HTMl标签中嵌套Jav…...

国产编程—— 仓颉

应用 仓颉编程语言是一款由华为主导设计和实现的面向全场景智能的编程语言,主要应用于以下领域: 中文字符编码和文本数据处理:仓颉编程语言充分利用汉字的结构特点来设计编码,为开发者提供了一种高效的方式来编码、存储和处理中…...

0X JavaSE-并发编程(锁)

1...

云计算【第一阶段(18)】磁盘管理与文件系统 分区格式挂载(一)

目录 一、磁盘基础 二、磁盘结构 2.1、机械硬盘 2.2、固态硬盘 2.3、扩展移动硬盘 2.4、机械磁盘的一些计算(了解) 2.5、磁盘接口类型 二、Linux 中使用的文件系统类型 2.1、磁盘分区的表示 2.1.1、主引导记录(MBR) 2.1.2、Linux中将硬盘、分…...

Flask-cache

Flask-cache 目录 Flask-cache基本使用配置可用参数SimpleCacheNullCacheFileSystemCacheRedisCacheRedisSentinelCacheRedisClusterCacheMemcachedCacheSASLMemcachedCacheUWSGICache Flask-Cache是一个强大的缓存库,为基于Flask的应用提供了简单易用的API和多种缓…...

【面试题】面试小技巧:如果有人问你 xxx 技术是什么?_面试问你对什么技术特别了解

前端工程越来越大,前面几种方案不能很好的支持单元测试。 在这样的背景下,React 诞生了。React 带来了新的思维模式,UI fn(props),React 中一个组件就是一个函数或者一个类,一个函数或者一个类就是一个基础单位&…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

三体问题详解

从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

SpringCloudGateway 自定义局部过滤器

场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...