Skip to content

浅拷贝和深拷贝

数组偏平化(拉平)

js
// 第一种方式 使用递归函数遍历旧数组
function flatArray(arr) {
    // 创建新的空数组
    let newArr = [];
    // 使用循环结构遍历 arr
    for (var i = 0; i < arr.length; i ++) {
        // 判断当前的元素是否是数组
        if (arr[i] instanceof Array) {
            // 递归调用
            newArr = newArr.concat(flatArray(arr[i]));
        } else {
            // 将该元素添加到新数组中
            newArr.push(arr[i]);
        }
    }
    // 返回新数组
    return newArr;
}

// 第二种方式 缺点是里面的元素都会转为字符串
nums.join().split(',');

// 第三种方式 数组的flat方法
nums.flat(Infinity);

对象的浅拷贝

数组的浅拷贝:

仅仅拷贝了对象的外表解构(一维),数组内嵌套的数据(地址)没有变化。

js
1. [...arr] 扩展运算符
2. arr.concat() 返回新的数组 ,参数是空表示自己
3. arr.slice()    返回新的数组,从头截取到尾
4. Array.from(arr) 返回新的数组,将可遍历对象转为纯数组。

对象的浅拷贝:

仅仅拷贝了对象的外表解构(一维),对象内嵌套的数据(地址)没有变化。

js
1. {...obj} 扩展运算符
2. Object.assign({}, obj) 返回新对象,利用对象合并实现对象浅拷贝

image-20240401134915774

JSON对象的拷贝

js
JSON.stringify()	将对象或数组转为json格式的字符串。参数是对象。
JSON.parse()	将json格式的字符串 恢复成对象或数组,参数是json格式的字符串。

对象的深拷贝

借助于JSON

js
// 1. 借助于JSON  无法拷贝方法,适合于纯数据对象,没有方法的对象叫做纯数据对象。
JSON.parse(JSON.stringify(obj));

借助于递归函数

js
/**
 * 判断数据的类型
 * @params 要判断类型的数据
 * @returns string 数据的类型
 判断数据类型
 Object.prototype.toString是顶层原型上的方法。返回值是 Object Object,是为了给Object的实例准备的
 通过指定Object this的指向那种数据类型,他的返回结果就是谁的类型,这是ES6的本身设计。
*/
function getType(data) {
    const typeStr = Object.prototype.toString.call(data);
    return typeStr.slice(8, typeStr.length-1);
};

/**
 * 实现对象和数组的深拷贝
 * @params 要拷贝的数据
 * @returns 拷贝好的数据
*/
function deepClone(obj) {
    // 判断 obj 是 Object 类型还是 Array 类型
    let res;
    if (getType(obj) === 'Object') {
        res = {};
    } else if (getType(obj) === 'Array') {
        res = [];
    } else {
        return obj;
    }

    // 遍历 Object数据或者Array数据
    for (let i in obj) {
        // 将obj中中的成员添加到 res
        res[i] = deepClone(obj[i]);
    }

    // 返回res
    return res;
}