【3】前端手撕-深浅拷贝

1. 浅拷贝

对于引用数据类型只拷贝第一层,若第一层中也存在引用数据类型,则拷贝的仅仅是地址,若该数据修改,则会影响原数据

示例数据

js 复制代码
const originalObj = {
    name: 'John',
    age: 30,
    address: {
        city: 'Beijing',
        country: 'China',
    },
    hobbies: ['reading', 'traveling', 'cooking'],
};

const originalArr = [1, 2, 3, { a: 4 }];

使用Object.assign()

js 复制代码
const shallowCopyObj = Object.assign({}, originalObj);

解构赋值

js 复制代码
// 对象
const shallowCopyObj2 = { ...originalObj };
// 数组
const shallowCopyArr4 = [...originalArr];

拷贝数组

js 复制代码
// 拷贝数组:使用Array.prototype.slice()
const shallowCopyArr = originalArr.slice();

// 拷贝数组:使用Array.prototype.concat()
const shallowCopyArr2 = originalArr.concat();

// 拷贝数组:使用Array.from()
const shallowCopyArr3 = Array.from(originalArr);

2. 深拷贝

深拷贝完全复制对象,如果对象中存在嵌套的引用数据类型,则会另外开辟一个空间来进行存储,拷贝后的对象与原对象互相独立,互不影响

递归实现深拷贝

js 复制代码
function deepClone(obj) {
    // 基础数据类型直接原样返回
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    // 处理数组
    if (Array.isArray(obj)) {
        return obj.map(deepClone);
    }

    const result = {};
    Object.keys(obj).forEach((key) => {
        // 只拷贝对象自己本身的属性,不拷贝原型链上的属性
        if (obj.hasOwnProperty(key)) {
            result[key] = deepClone(obj[key]);
        }
    });

    return result;
}

递归实现深拷贝进阶版:解决循环引用,Date和正则的拷贝

js 复制代码
function deepCloneCircular(obj, visited = new WeakMap()) {
    // 基础数据类型直接原样返回
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    // 检查循环引用
    if (visited.has(obj)) {
        return visited.get(obj);
    }

    if (obj instanceof Date) {
        return new Date(obj);
    }

    if (obj instanceof RegExp) {
        return new RegExp(obj.source, obj.flags);
    }

    const result = Array.isArray(obj) ? [] : {};

    // 保存引用避免循环引用
    visited.set(obj, result);

    Object.keys(obj).forEach((key) => {
        // 只拷贝对象自己本身的属性,不拷贝原型链上的属性
        if (obj.hasOwnProperty(key)) {
            result[key] = deepCloneCircular(obj[key], visited);
        }
    });

    return result;
}

JSON方法实现深拷贝

js 复制代码
function deepCloneByJSON(obj) {
    return JSON.parse(JSON.stringify(obj));
}

局限性:

  1. 无法拷贝函数:如果对象中存在函数,拷贝结果中函数将会丢失
  2. 无法拷贝undefined:拷贝过程中值为undefined的属性会丢失
  3. 无法拷贝Symbol:拷贝过程中如果键名为Symbol也会拷贝丢失
  4. Date类型会被转为字符串
  5. 正则对象在拷贝过程中也会丢失
  6. NaNInfinity在拷贝过程中会变为null
  7. 若对象中存在循环饮用,则会报错
  8. 对于Map,Set,WeakMap,WeakSet的拷贝结果会变为{}空对象

使用现代浏览器支持方法

js 复制代码
// 现代浏览器原生支持 (Chrome 98+, Firefox 94+, Node 17+)
const result = structuredClone(originalObj);
相关推荐
鹏多多1 小时前
PC 网站接入微信登录,这 10 个坑我替你踩完了!
前端·javascript·vue.js
用户298698530142 小时前
React 中 HTML 内容转 Word 文档的实现方案
javascript·react.js·html
mONESY2 小时前
我用 Next.js 16 + Supabase 从零做了个「背单词」H5 应用
javascript
boooooooom2 小时前
手把手做一个图 RAG 烹饪问答系统:Neo4j + Milvus + LLM 的工程实践
前端·javascript·后端
染指11105 小时前
103.RAG-LLamaIndex后端rag问答-聊天接口
前端·javascript·vue.js·人工智能
单线程_0113 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
小磊哥er15 小时前
深入解构Claude Code - 第 8 篇 · 数据放哪、钱怎么算
javascript·ai编程
kyriewen17 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
默_笙19 小时前
🔥 让 AI 帮我写完整个 Next.js 博客:框架就是 AI 的"上下文 buff"
前端·javascript
喵本喵叁肆1 天前
06-M6-部门过滤与综合研判-从问答机到研判助手
前端·javascript·jquery