Skip to content

前言

JavaScript的数据类型有两大类:

  • 基本数据类型

  • 引用类型

基本数据类型

stringnumbernullundefinedbooleansymbol(ES6新增) 变量值存放在栈内存中,可直接访问和修改变量的值 基本数据类型不存在拷贝,好比如说你无法修改数值1的值

引用类型

Object Function RegExp Math Date 值为对象,存放在堆内存中 在栈内存中变量保存的是一个指针,指向对应在堆内存中的地址。 当访问引用类型的时候,要先从栈中取出该对象的地址指针,然后再从堆内存中取得所需的数据

浅拷贝

浅拷贝赋值引用地址,修改值会影响原始值(若属性的值未原始类型可能不会影响,依拷贝方法而定

  • 直接赋值;
    • 任何操作都会影响原数组;
JavaScript
let obj2 = obj1;
  • Object.assign;
    • 拷贝属性值,假如属性值是一个对象的引用,那么也会指向那个引用;
JavaScript
let obj2 = Object.assign({},obj1);
  • Array.prototype.concat();
    • 合并多个数组;
    • 拷贝规则同Object.assign;
JavaScript
let arr2 = arr1.concat(...arr);
  • Array.prototype.slice();
    • 提取数组;
    • 参数(可选):startIndex,endIndex(与索引值一致);
    • 拷贝规则同Object.assign;
JavaScript
let arr2 = arr1.slice(start,end);
  • 扩展运算符(...);
    • 拷贝规则同Object.assign;
JavaScript
let obj2 = {obj1} or [...obj1];
  • lodash(_.clone());
    • 拷贝规则同Object.assign;
JavaScript
let obj2 = _.clone(obj1);

深拷贝

拷贝所有的属性,并且地址也与原来的不同,这样的话,你改变当前的属性也不会影响原来的

  • JSON.parse(JSON.stringify());
    • 但是该方法有以下几个问题:

    • 会忽略 undefined

    • 会忽略 symbol

    • 不能序列化函数

    • 不能解决循环引用的对象

    • 不能正确的处理 new Date()

    • 不能处理正则

JavaScript
function deepClone(obj) {
  var _obj = JSON.stringify(obj)
  var objClone = JSON.parse(_obj)
  return objClone
}
  • 递归赋值;
JavaScript
function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            //判断是否为自身属性
            if(obj.hasOwnProperty(key)){
                //判断ojb子元素是否为对象,如果是,递归复制
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}
  • lodash(_.cloneDeep());
JavaScript
let obj2 = _.cloneDeep(obj1);