深拷贝与浅拷贝的区别

浅拷贝:只复制对象的第一层属性。如果属性值是引用类型(如对象、数组),拷贝的是它的内存地址,新旧数据会互相影响。
深拷贝:递归复制对象的所有层级,生成一个完全独立的新对象,新旧数据互不影响。

  1. 浅拷贝(Shallow Copy)
    做了什么:创建一个新对象,将原对象的基本类型属性复制一份,但对于引用类型属性,只复制它的引用(指针)。
    在 Vue 中的表现:
    javascript
    data() {
    return {
    user: {
    name: '张三',
    info: { age: 18 }
    }
    }
    },
    methods: {
    handleCopy() {
    // 使用展开运算符进行浅拷贝
    const newUser = { ...this.user };

    // 修改基本类型(第一层),原数据不受影响
    newUser.name = '李四';
    console.log(this.user.name); // 输出 '张三'

    // 修改引用类型(深层),原数据会跟着变!
    newUser.info.age = 20;
    console.log(this.user.info.age); // 输出 20 原数据被意外修改了
    }
    }
    常见的浅拷贝方式:
    展开运算符:{ ...obj } 或 [...arr]
    Object.assign({}, obj)
    Array.prototype.slice()、Array.prototype.concat()

  2. 深拷贝(Deep Copy)
    做了什么:完整地复制整个对象结构,在内存中开辟一块全新的空间,与原对象彻底“断开关联”。
    在 Vue 中的表现:
    javascript
    methods: {
    handleDeepCopy() {
    // 使用 JSON 方法进行深拷贝(注意:有局限性)
    const newUser = JSON.parse(JSON.stringify(this.user));

    // 修改深层属性,原数据纹丝不动
    newUser.info.age = 20;
    console.log(this.user.info.age); // 输出 18 完全独立
    }
    }
    常见的深拷贝方式:
    JSON.parse(JSON.stringify(obj)):最常用,但有缺陷(无法拷贝函数、undefined、Symbol、循环引用等)。
    structuredClone(obj):现代浏览器的原生 API,功能比 JSON 方法强大,支持 Date、Map、Set 等,但仍不支持函数。
    lodash.cloneDeep(obj):第三方库,功能最全面、最可靠,几乎能处理所有情况。

  3. 在 Vue 中的实际应用场景
    场景一:编辑弹窗(必须用深拷贝)
    这是最常见的坑。点击编辑时,如果直接把 row 对象赋值给表单,修改表单会直接改掉列表数据。

javascript
// 错误做法(浅拷贝)
this.editForm = this.row; // 修改 editForm 会直接污染列表
// 正确做法(深拷贝)
this.editForm = JSON.parse(JSON.stringify(this.row));
// 或 this.editForm = _.cloneDeep(this.row);
场景二:组件 Props(视情况使用)
父组件传下来的 props 不建议直接修改。如果你需要基于它做计算,用浅拷贝就够了(只要不改深层)。
javascript
props: ['config'],
computed: {
localConfig() {
// 只改第一层,用浅拷贝即可
return { ...this.config, visible: true };
}
}
场景三:Vuex 状态修改(必须用深拷贝)
在 mutations 或 actions 中,永远不要直接修改 state 中的引用类型,除非你调用 Vue 提供的变更方法(如 Vue.set)。
javascript
// 从 state 取出数组,想 push 新元素
const newList = state.list; // 这是引用
newList.push(item); // 虽然可以,但不符合规范
// 应该深拷贝一份再操作,最后重新赋值(或使用 Vue.set)
const newList = JSON.parse(JSON.stringify(state.list));
newList.push(item);

posted @ 2026-07-09 12:48  小肥123  阅读(7)  评论(0)    收藏  举报