深拷贝是 JavaScript 中用于复制对象的一种方式,它的核心特点是创建一个完全独立的新对象,新对象与原对象不会共享内存地址,修改新对象的属性不会影响原对象,反之亦然。
getHomeRoute() {
let homeRoute = null;
// 深拷贝菜单数据(避免修改原数据)
let routes = JSON.parse(JSON.stringify(this.menuData));
// 调用递归方法查找首页路由
homeRoute = this.getRouteByName(routes);
return homeRoute;
},
getHomeRoute()
方法里的let routes = JSON.parse(JSON.stringify(this.menuData));
就是典型的深拷贝实现,我们结合这段代码来详细理解:
代码注释提到 “避免修改原数据”,这正是深拷贝的核心作用。
this.menuData
是组件接收的菜单数据(父组件传递的 props
),属于需要保护的原始数据。如果直接操作 this.menuData
(比如在递归查找首页路由时修改其属性),会导致原数据被污染,可能引发不可预知的问题(比如父组件中该数据同步变化)。
通过深拷贝生成 routes
后,后续的递归操作(getRouteByName(routes)
)只会修改 routes
,不会影响 this.menuData
。
深拷贝与浅拷贝的区别
浅拷贝:只复制对象的表层属性,若对象包含嵌套对象(如数组、子对象),浅拷贝会让新对象与原对象共享嵌套对象的内存地址。
例如:let routes = [...this.menuData];
(数组浅拷贝),若this.menuData
中的元素是对象,修改routes
中的元素属性会影响原数组。深拷贝:会递归复制对象的所有层级,包括嵌套对象,新对象与原对象完全独立。
例如代码中的JSON.parse(JSON.stringify(...))
,即使this.menuData
是多层嵌套的数组 / 对象,routes
也会成为一个完全独立的副本。
代码中深拷贝的实现方式
JSON.parse(JSON.stringify(this.menuData))
是 JavaScript 中最常用的深拷贝技巧,原理是:
JSON.stringify(this.menuData)
:将对象转换为 JSON 字符串(序列化),剥离所有内存引用。JSON.parse(...)
:将 JSON 字符串重新转换为对象(反序列化),生成全新的内存地址。
这种方式简单有效,但有局限性(比如无法拷贝函数、正则、循环引用等),不过对于 menuData
这类纯数据(数组 + 对象 + 基本类型)的菜单结构,完全适用。
总结
在这段代码中,深拷贝的作用是保护原始菜单数据不被后续操作修改,通过 JSON.parse(JSON.stringify(...))
生成独立副本 routes
,确保递归查找首页路由的过程中,this.menuData
保持纯净,符合 Vue 中 “props 单向数据流” 的设计原则(子组件不应修改父组件传递的 props)。