js中数据的深浅拷贝

数据深浅拷贝

前言: js中数据分为基本类型和引用类型,基本类型变量在使用时可以被直接访问,不存在深浅拷贝一说;而引用类型,由于其值变量存放在堆中,栈中存放的是指向堆中值的地址,所有在使用引用类型变量时,使用的是栈中的引用地址。

深浅拷贝:简单来说就是把object类型的数据复制后进行修改,修改后的值对原值没有影响为深拷贝;反之,改变了原值就是浅拷贝。

由于object数据在复制后操作会影响到原值,在某些情况下并不是我们想要的,想要解决这个问题就要用到数据的深拷贝,对于数据深拷贝,本人比较喜欢如下两种,尤其是第一种在使用起来非常简单暴力:

  1. 把object转成json字符串,在将json串反转成object对象
let obj = {
	name: '美眉',
	gender: '女',
	age: '18',
	tag: ['美少女','小可爱','白富美']
}
let obj1 ;
let strObj = JSON.stringify(obj); 
obj1 = JSON.parse(strObj);
//obj1 = SON.parse(JSON.stringify(object));

花里胡哨的深拷贝JSON.parse(JSON.stringify(object)) 一句代码搞定 0.0 。

  1. 创建新的对象,递归循环直到其为基本类型然后复制过去

deepCopy: (data) => {
    let copyObj = data instanceof Array ? [] : {}
    for(item in data){
        if(typeof(item) === 'object'){
            obj[item] = deepCopy(data[item])
        }else{
            obj[item] = data[item]
        }
    }
    return copyObj
}

<think>首先,用户要求使用中文回答问题。所以,我的整个响应必须用中文。 问题:详细讲解一下JavaScript中的深浅拷贝。 我需要提供详细的解释。然后,在回答结束后,必须提出3-5个相关问题。这些相关问题必须以“§§相关问题§§”开头,并且必须输出在回答的末尾。不能换行分散,意思是“§§相关问题§§”必须在一行中完整输出,然后紧接着列出问题。 从示例格式中: - 回答部分:解释了快速排序,并给出了代码。 - 然后,直接输出“§§相关问题§§”,没有换行。 - 之后是相关问题列表,以数字点(如1. ···)列出。 所以,我的响应结构: 1. 详细讲解JavaScript中的深浅拷贝。 2. 在讲解结束时,直接输出“§§相关问题§§”。 3. 然后列出3-5个相关问题,每个问题以数字点开头(如1. 问题1)。 内容要点: - **深拷贝(Deep Copy)**:创建一个新对象,并递归地复制所有嵌套对象,使得新对象与原始对象完全独立,修改新对象不会影响原始对象。 - **浅拷贝(Shallow Copy)**:创建一个新对象,只复制对象的第一层属性。如果属性是引用类型(如数组、对象),则复制的是引用,所以修改嵌套对象会影响原始对象。 在JavaScript中,实现深浅拷贝的方法: - 浅拷贝: - 使用 `Object.assign({}, obj)` - 使用展开运算符 `{...obj}` - 对于数组:`Array.from(arr)`, `arr.slice()`, `[...arr]` - 深拷贝: - 使用 `JSON.parse(JSON.stringify(obj))`,但有限制:不能处理函数、undefined、循环引用等。 - 使用递归函数手动实现深拷贝。 - 使用第三方库如 Lodash 的 `_.cloneDeep()`。 我需要详细讲解这些,确保解释清晰。 之后,提出3-5个相关问题。相关问题应该基于用户的提问和我的回答,帮助深化理解或探索相关主题。 可能的相关问题: 1. 深浅拷贝在实际开发中的常见应用场景是什么? 2. 在JavaScript中,如何实现一个深拷贝函数来处理循环引用? 3. 除了JSON方法,还有哪些深拷贝的实现方式? 4. 深浅拷贝的性能差异如何?在什么情况下应该选择深拷贝而不是浅拷贝? 5. 在ES6中,有哪些新特性可以简化深浅拷贝的操作? 确保有3-5个问题。 最后,输出格式: - 回答部分:用中文。 - 结束时,直接输出“§§相关问题§§”,然后列出问题。 - 例如: §§相关问题§§ 1. 问题1 2. 问题2 3. 问题3 现在,构建响应。</think>### JavaScript中的深浅拷贝详解 在JavaScript中,深浅拷贝是处理对象复制的重要概念,主要用于避免引用类型数据共享带来的副作用。以下从定义、区别、实现方法和注意事项进行详细讲解。 #### 1. **浅拷贝(Shallow Copy)** - **定义**:创建一个新对象,只复制对象的第一层属性(基本类型值会被复制,引用类型值则复制其引用地址)。因此,如果原对象的属性包含嵌套对象,修改新对象的嵌套属性会影响原对象。 - **实现方法**: - **对象浅拷贝**: - 使用 `Object.assign()`:`const newObj = Object.assign({}, originalObj);` - 使用展开运算符(ES6):`const newObj = { ...originalObj };` - **数组浅拷贝**: - 使用 `Array.from()`:`const newArr = Array.from(originalArr);` - 使用 `slice()`:`const newArr = originalArr.slice();` - 使用展开运算符:`const newArr = [...originalArr];` - **示例代码**: ```javascript const obj = { a: 1, b: { c: 2 } }; const shallowCopy = { ...obj }; shallowCopy.b.c = 3; // 修改嵌套属性 console.log(obj.b.c); // 输出 3,原对象也被修改 ``` - **特点**: - 简单高效,适合拷贝简单结构。 - 缺点:嵌套对象共享引用,可能导致意外修改。 #### 2. **深拷贝(Deep Copy)** - **定义**:创建一个新对象,并递归地复制所有层级属性(包括嵌套对象),使得新对象与原始对象完全独立。修改新对象不会影响原对象。 - **实现方法**: - **JSON方法**(简单但有限制): - `const newObj = JSON.parse(JSON.stringify(originalObj));` - 缺点:无法复制函数、`undefined`、`Symbol`、循环引用或日期对象(会被转为字符串)。 - **递归手动实现**: - 自定义函数处理各种类型: ```javascript function deepClone(obj, map = new Map()) { if (obj === null || typeof obj !== 'object') return obj; if (map.has(obj)) return map.get(obj); // 处理循环引用 const clone = Array.isArray(obj) ? [] : {}; map.set(obj, clone); for (const key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = deepClone(obj[key], map); } } return clone; } const newObj = deepClone(originalObj); ``` - **第三方库**: - Lodash 的 `_.cloneDeep()`:`const newObj = _.cloneDeep(originalObj);` - **示例代码**: ```javascript const obj = { a: 1, b: { c: 2 } }; const deepCopy = JSON.parse(JSON.stringify(obj)); deepCopy.b.c = 3; // 修改嵌套属性 console.log(obj.b.c); // 输出 2,原对象不受影响 ``` - **特点**: - 完全隔离数据,适合复杂对象。 - 缺点:性能开销大(尤其递归深层次对象),需处理边界情况如循环引用。 #### 3. **关键区别与注意事项** - **核心区别**: - 浅拷贝:只复制一层,嵌套对象共享引用。 - 深拷贝:复制所有层级,嵌套对象独立。 - **使用场景**: - 浅拷贝:状态管理(如React的浅比较)、简单数据传递。 - 深拷贝:数据持久化、不可变数据更新(如Redux reducer)。 - **常见陷阱**: - 循环引用:手动深拷贝需使用WeakMap或Map避免无限递归。 - 性能:深拷贝大对象可能阻塞主线程,优先考虑浅拷贝或Immutable.js等库。 - 类型兼容:JSON方法会丢失特殊类型(如函数),需手动处理。 #### 4. **总结** 深浅拷贝的选择取决于数据结构和使用需求:浅拷贝快速但共享引用,深拷贝安全但成本高。在实际开发中,推荐使用Lodash等库简化实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值