实现深拷贝的方式:1、赋值;2、解构赋值;3、JSON.parse(JSON.stringify())
1、赋值
一、对于基本数据类型(Number,String, Boolean….)来说,与其说是深拷贝,严格来说,它们叫做赋值。
- let a = 5;
- let b = a;
- b = 3;
- console.log(a, b); // 5 3
二、对于引用数据类型(Object,Array)的深浅拷贝有很多方法,我们依次来看一下:
1. 直接通过赋值,然后进行修改,结果是浅拷贝。
- // 数组与对象的赋值,都叫做浅拷贝
- let arr = [1, 2, 3];
- let newArr = arr;
- newArr.push(4);
- console.log(arr, newArr);
2. 使用数组解构进行拷贝:分为两种情况:
情况一:对一维数组使用解构,进行拷贝,结果是深拷贝
- let arr = [1, 2, 3];
- let newArr = [...arr];
- newArr.push(4);
- console.log(arr, newArr);
情况二:对多维数组使用解构,进行拷贝,结果是浅拷贝
- let arr = [[1, 2, 3], [4, 5, 6]];
- let newArr = [...arr];
- newArr[0].push(4);
- console.log(arr, newArr);
3. 使用JSON.Parse(JSON.stringify()),实现深拷贝。
先将一个JavaScript对象转为一个JSON字符串,再转化为JSON对象。
缺点:a、不能拷贝对象上的原型连的属性和方法; b、不能拷贝属性是模板字符挥着正则表达式,c、不能拷贝value值是new Date(),d、不能拷贝value值是:undefined、symbol 和函数这三种情况,会直接忽略。
- let list = [
- { id: 1, name: '张三' },
- { id: 2, name: '李四' },
- { id: 3, name: '王五' },
- ]
- let newList = JSON.parse(JSON.stringify(list));
- newList.push({ id: 4, name: '兜兜' });
- console.log(list, newList);
三. 实现深拷贝的Function函数
写法一:
- let objc = {
- name: '张三', // 基本数据类型
- age: 18, // 基本数据类型
- objInfo: { // 引用数据类型:Object
- sex: '女',
- hobby: '游泳'
- },
- arr: [1, 2, 3] // 引用数据类型: Array
- }
-
- function deepClone(info) {
- // 数组的constructor会指向Array() { [natice code] }
- // 对象的constructor会指向Object() { [native code] }
- const targetInfo = info.constructor === Array ? [] : {};
- // for in 即可以遍历对象,也可以遍历数组
- for (let keys in info) {
- if (info.hasOwnProperty(keys)) {
- // keys可能有三种类型:基本数据类型, Object, Array
- // 如果是引用数据类型
- if (info[keys] && typeof info[keys] === 'object') {
- // 这行可写可不写
- // targetInfo[keys] = info[keys].constructor === Array ? [] : {};
- // 递归
- targetInfo[keys] = deepClone(info[keys])
- } else { // 如果是基本数据类型
- targetInfo[keys] = info[keys];
- }
- }
- }
- return targetInfo
- }
-
- let newObj = deepClone(objc)
- newObj.name = '李四'
- newObj.arr.push('打豆豆')
- console.log(objc, newObj);
写法二:
- let obj = {
- name: '穗穗',
- age: 18,
- info: {
- sex: '女',
- height: 162
- },
- arr: [1,2,3]
- }
- const obj1 = deepClone(obj)
-
- function deepClone(info) {
- // 判断info的数据类型,如果是基本数据类型或为赋值,直接返回
- // 如果info未赋值 ==> let info; info=undefined
- // info == null 相当于if (info === null || info === undefined)
- // info == null为true,info === null为false,所以此处用==
- if (typeof info !== 'object' || info == null) {
- return info;
- }
- let resultObj;
- if (info instanceof Array) {
- resultObj = []
- } else resultObj = {};
- for (let key in info) {
- if (info.hasOwnProperty(key)) {
- resultObj[key] = deepClone(resultObj[key])
- }
- }
- return resultObj
- }
写法三:
- // 深拷贝函数
- function deepClone(obj) {
- // 1 判断是否是非应用类型或者null
- if (typeof obj !== 'object' || obj == null) return obj
- // 2 创建一个容器
- let cloneObj = new obj.constructor()
- // 3 拿到对象的keys,给容器赋值
- Object.keys(obj).forEach(v => cloneObj[v] = deepClone(obj[v]))
- // 4 返回容器
- return cloneObj
- }