【前端学习——js篇】4.浅拷贝与深拷贝

具体可见https://github.com/febobo/web-interview

4.浅拷贝与深拷贝

①栈内存与堆内存

栈内存(Stack Memory)

  • 栈内存用于存储基本类型的变量和引用类型的变量引用(即指向堆内存中实际数据的指针)。
  • 当一个函数被调用时,会创建一个称为“执行上下文”的栈帧,其中包含函数的参数、局部变量和返回地址。
  • 栈内存是一个后进先出(LIFO)的数据结构,它在程序执行期间动态地增加和减少内存空间。
  • 变量在栈内存中的分配是自动的,当变量超出作用域时会被自动销毁。
//1.基本数据
整数(例如:let num = 10;)
浮点数(例如:let floatNum = 3.14;)
布尔值(例如:let isTrue = true;)
字符串(例如:let str = "Hello";)
//2.函数调用
function add(a, b) {return a + b;
}let result = add(5, 3); // 函数调用会在栈内存中创建执行上下文

基本数据类型和函数调用的数据存储在栈内存中。
【具体例子】

let a = 10;
let b = a; // 赋值操作
b = 20;
console.log(a); // 10值

在这里插入图片描述

堆内存(Heap Memory)

  • 堆内存用于存储引用类型的数据,如对象和数组。
  • 在堆内存中,数据的大小不固定,可以动态地分配和释放内存。
  • 当在栈内存中创建一个引用类型的变量时,实际的数据存储在堆内存中,而栈内存存储的是对数据的引用。
  • 堆内存的数据需要手动的分配和释放,js引擎通过垃圾回收机制来自动管理堆内存中不在使用的数据,以防止内存泄露。
//1.对象
let person = {name: "Alice",age: 30
};
//2.数组
let numbers = [1, 2, 3, 4, 5];
//3.动态分配的对象
let user = null; // 声明一个变量
user = {name: "Bob",age: 25
};
//4.使用构造函数创建对象
function Person(name, age) {this.name = name;this.age = age;
}let person1 = new Person("Charlie", 35);

对象、数组和动态分配的对象存储在堆内存中。
【具体例子】

var obj1 = {}
var obj2 = obj1;
obj2.name = "wow";
console.log(obj1.name); // wow

在这里插入图片描述

【总结】

  • 栈内存用于存储基本类型的变量和引用类型的变量的引用,具有自动分配和释放内存的特性。
  • 堆内存用于存储引用类型的数据,具有动态分配和手动释放内存的特性。
②浅拷贝

浅拷贝指的是创建新的数据,这个数据是对原数据属性值的精准拷贝。当属性是基本类型,则拷贝的是基本类型的值;如果是引用类型,则拷贝的是内存地址。即浅拷贝是拷贝一层,深层次的引用类型则是共享地址。

//例1
let obj1 = { name: "Alice", age: [30,21] };
let shallowCopy = Object.assign({}, obj1);shallowCopy.age[0] = 40;
console.log(obj1.age); // 输出 40,原始对象改变shallowCopy.name = "Bob";
console.log(obj1.name); // 输出 "Alice",原始对象不会受到影响

在例1中,由于属性name是基本类型,所以shallowCopy直接拷贝的数据,对基本数据值修改不会影响原始数据;而age是数组,则拷贝的是数组的地址,所以对age进行修改,则会影响到原始数据。

JavaScript中,存在浅拷贝的现象有:

  • Object.assign

  • Array.prototype.slice(), Array.prototype.concat()

  • 使用拓展运算符实现的复制

Object.assign

Object.assign()静态方法将一个或者多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象。


//Object.assign
var obj = {age: 18,nature: ['smart', 'good'],names: {name1: 'fx',name2: 'xka'},love: function () {console.log('fx is a great girl')}
}
var newObj = Object.assign({}, obj); //浅拷贝

Array.prototype.concat()

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。


//Array.concat
const Arr = ["One", "Two", "Three"]
const fxArrs1 = Arr.concat()
fxArrs1[1] = "hello";
console.log(Arr) // ["One", "Two", "Three"]
console.log(fxArrs1) // ["One", "hello", "Three"]

拓展运算符

扩展运算符(spread) 是三个点(…),它如同 rest 运算,将一个数组转为用逗号分割的参数序列。


const fxArr = ["One", "Two", "Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
③深拷贝

深拷贝开辟一个新的栈,两个对象属性完全相同,但是对应两个不同的地址;对一个对象进行修改,不会影响到另一个对象。

// 使用 Lodash 库中的深拷贝方法
//例1
const _ = require('lodash');let obj1 = { name: "Alice", nestedObj: { key: "value" } };
let deepCopy = _.cloneDeep(obj1);deepCopy.nestedObj.key = "new value";
console.log(obj1.nestedObj.key); // 输出 "value",原始对象不受影响

JS中,常见的深拷贝方式有:

  • _.cloneDeep()

  • jQuery.extend()

  • JSON.stringify()

  • 手写循环递归

_.cloneDeep()

_.cloneDeep是lodash库中一个用于实现深拷贝方法,它会递归地赋值一个对象或数组及其所有嵌套对象和数组,从而创建一个完全独立的副本。


//见例1

jQuery.extend()

在 jQuery 中,可以使用 jQuery.extend() 方法来实现对象的深拷贝。这个方法可以用于将一个或多个对象的内容合并到目标对象中,如果目标对象中已经存在相同的属性,则会被覆盖;在某种程度上也可以实现深拷贝。当你将一个空对象作为目标对象,并将需要复制的对象作为参数传递给 jQuery.extend() 方法时,它会创建目标对象的一个深层副本。


let obj1 = { name: "Alice", nestedObj: { key: "value" } 
};let deepCopy = $.extend(true, {}, obj1);deepCopy.nestedObj.key = "new value";
console.log(obj1.nestedObj.key); // 输出 "value",原始对象不受影响

JSON.stringify()

JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。


    const obj = {name:{key : "a"},name1: undefined,name3: function () { },name4: Symbol('A')}const obj2 = JSON.parse(JSON.stringify(obj));obj.name.key = 'b'console.log(obj2); // 输出a

但是这种方式存在弊端,会忽略undefinedsymbol函数

循环递归

    function deepClone(obj, hash = new WeakMap()) {if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作if (obj instanceof Date) return new Date(obj);if (obj instanceof RegExp) return new RegExp(obj);// 可能是对象或者普通的值  如果是函数的话是不需要深拷贝if (typeof obj !== "object") return obj;// 是对象的话就要进行深拷贝if (hash.get(obj)) return hash.get(obj);let cloneObj = new obj.constructor();// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身hash.set(obj, cloneObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {// 实现一个递归拷贝cloneObj[key] = deepClone(obj[key], hash);}}return cloneObj;}const obj = {name: {key: "a"},name1: undefined,name3: function () { },name4: Symbol('A')}const obj2 = deepClone(obj)obj2.name.key = "hello"console.log(obj); //输出a
总结

在这里插入图片描述

前提为拷贝类型为引用类型的情况下:

  • 浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址

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

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

相关文章

Mysql的日志管理,备份与回复

目录 一、Mysql日志管理 1、日志的默认位置及配置文件 2、日志分类 2.1错误日志 2.2通用查询日志 2.3二进制日志 2.4慢查询日志 2.5中继日志 3、日志配置 4、日志查询 4.1查询通用日志是否开启 4.2查询二进制日志是否开启 4.3查看慢查询日志是否开启 4.4查询慢查…

Vivado Lab Edition

Vivado Lab Edition 是完整版 Vivado Design Suite 的独立安装版本 , 包含在生成比特流后对赛灵思 FPGA 进行编程和 调试所需的所有功能。通常适用于在如下实验室环境内进行编程和调试: 实验室环境中的机器所含磁盘空间、内存和连 接资源较少。Vivad…

python数据实时传给unity工程并绘制出来

python # 服务器端代码 import socket import random import struct import time# 创建一个服务器Socket server_socket socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 监听的地址和端口 host 127.0.0.1 port 12345# 绑定地址和端口 server_socket.bind((host, port…

纯分享万岳外卖跑腿系统客户端源码uniapp目录结构示意图

系统买的是商业版,使用非常不错有三端uniapp开源代码,自从上次分享uniapp后有些网友让我分享下各个端的uniapp下的各个目录结构说明 我就截图说以下吧,

【Java - 框架 - Lombok】(1) 普通Java项目通过Lombok+Logback完成日志的创建使用 - 快速上手

普通Java项目通过"Lombok""Logback"完成日志的创建使用 - 快速上手&#xff1b; 步骤A 说明 创建"Maven"项目&#xff1b; 图片 步骤B 说明 添加相关依赖项&#xff1b; 图片 代码 <!-- "Lombok"依赖项--> <dependency>&…

c++核心学习--继承2

4.6.7多继承语法 4.6.8菱形继承 利用虚继承解决菱形继承的问题&#xff1a;继承之前加上关键字virtual变为虚继承

经纬恒润RTaW-Pegase:车载网络通信建模与时间特性分析工具

▎RTaW简介 RTaW-Pegase是由法国国家信息与自动化研究所&#xff08;INRIA&#xff09;旗下的RTaW公司开发的产品。它主要用于构建和优化汽车、航空航天以及工业领域的通信网络&#xff0c;包括时间敏感网络&#xff08;TSN&#xff09;、CAN&#xff08;FD&#xff0c;XL&…

react-navigation:

我的仓库地址&#xff1a;https://gitee.com/ruanjianbianjing/bj-hybrid react-navigation&#xff1a; 学习文档&#xff1a;https://reactnavigation.org 安装核心包: npm install react-navigation/native 安装react-navigation/native本身依赖的相关包: react-nativ…

开源 | 电动自行车充换电解决方案,从智能硬件到软件系统,全部自主研发

文章目录 一、产品功能部分截图1.手机端&#xff08;小程序、安卓、ios&#xff09;2.PC端 二、小程序体验账号以及PC后台体验账号1.小程序体验账号2.PC后台体验账号关注公众号获取最新资讯 三、产品简介&#xff1f;1. 充电桩云平台&#xff08;含硬件充电桩&#xff09;&…

Codeforces Round 841 (Div. 2) C. Even Subarrays

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e9, maxm 4e4 5; co…

Java学习之方法

目录 方法 方法声明格式&#xff1a; 调用方式&#xff1a; 详细说明 示例 --方法的声明及调用 语句块 练习 方法的重载(overload) 构成条件 示例 --方法重载 递归结构 缺陷 方法 方法(method)&#xff1a;一段用于完成特定功能的代码片段&#xff0c;类似于其他语…

opencv 十九 python下实现多线程间rtsp直播流的复用

在多线程拉流的任务场景中&#xff0c;有时需要将一个rtsp拉取多次&#xff0c;每重新打开一次rtsp视频流就要多消耗一次带宽&#xff0c;为此基于类的静态对象实现rtsp视频流的复用。 1、实现代码 import threading import cv2,time #接收摄影机串流影像&#xff0c;采用多线…

【嵌入式机器学习开发实战】(七)—— 政安晨:通过ARM-Linux掌握基本技能【环境准备:树莓派】

ARM-Linux是一种针对ARM架构的操作系统&#xff0c;它的设计目标是在低功耗、低成本的硬件平台上运行。ARM-Linux可以运行在多种ARM处理器上&#xff0c;包括树莓派。 树莓派&#xff08;Raspberry Pi&#xff09;是一款基于ARM架构的单板计算机&#xff0c;由英国的树莓派基金…

【系统架构师】-第12章-信息系统架构

信息系统架构(ISA)是指对某一特定内容里的信息进行统筹、规划、设计、安排等一系列有机处理的活动。 为了更好地理解信息系统架构的定义&#xff0c; 特作如下说明: (1)架构是对系统的抽象&#xff0c;它通过描述元素、元素的外部可见属性及元素之间的关系来反映这种抽象。因此…

open_clip仓库成分与模型文件model.py 介绍

起因&#xff1a; 在DA-CLIP的开源库的DA-CLIP.md中自述该项目基于CLIP 和open_clip&#xff0c;在之前的退化类型检测中 我一度以为仓库只是使用了CLIP 的源码&#xff0c; 然而当发现缺少da-clip的模型名称时&#xff0c;我发现DA-CLIP使用的完全是open_clip的代码版本&#…

16.JRE和JDK

程序员在编写代码的时候其实是需要一些环境&#xff0c;例如我们之前写的HelloWorld。我们需要的东西有JVM、核心类库、开发工具。 1、JVM&#xff08;Java Virtual Machine&#xff09;&#xff1a;Java虚拟机&#xff0c;真正运行Java程序的地方。没有虚拟机&#xff0c;代码…

C语言例4-9:格式字符s的使用例子

代码如下&#xff1a; //格式字符s的使用例子 #include<stdio.h> int main(void) {printf("%s,%5s,%-5s\n","Internet","Internet","Internet");//以三种不同格式&#xff0c;输出字符串printf("%10.5s,%-10.5s,%4.5s\n&q…

rtthread studio 基于bsp生成代码stm32l475正点原子潘多拉,以及硬件配置

1、基于bsp生成代码 rtthread studio 很强大的一个功能就是可以根据芯片或者bsp 生成驱动代码&#xff0c;而且rtthread内核 已经集成到了代码中&#xff01;&#xff01;只需要关注于如何使用硬件和设备完成我们想要的功能就可以&#xff1b; 它的官网文档也特别详细&#x…

实用有趣的宝藏网站推荐!【第二期】

上次给大家推荐了10个宝藏网站&#xff08;http://t.csdnimg.cn/qcRWY&#xff09;&#xff0c;这次我又来啦&#xff01; 话不多说&#xff0c;直接开始&#xff01; 先收藏&#xff0c;防止以后找不到了&#xff01; 整理不易&#xff0c;顺便把赞留下吧&#xff01; 1. 爱…

江苏开放大学2024年春《市政管理学050011》第一次形考作业参考答案

答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 电大搜题 多的用不完的题库&#xff0c;支持文字、图片搜题…