常见的拷贝方式

174 阅读2分钟

写在前面

使用场景

在我们日常开发当中,我们经常会遇到深拷贝的场景,比如使用Vue技术栈的时候,我们需要把this.updateInfo中的数据传递给接口,而若干数据类型又不是我们预期想要的,这个时候怎么办呢?

使用深拷贝的方式,把this.updateInfo的数据拷贝一份,从而不影响原来的数据。

使用递归的方式

 function deepCopy (obj) {
            var result = Array.isArray(obj) ? [] : {};
            for(var key in  obj){
                if(obj.hasOwnProperty(key)){
                   if(typeof obj[key] === 'object' && obj[key]){
                       result[key] = deepCopy(obj[key])
                   }else{
                       result[key] = obj[key]
                   }
                }
            }
            return result
   }

使用JSON.parse(JSON.stringify())的方式

     function deepCopy (obj){
            return JSON.parse(JSON.stringify(obj))
        }
         
        var obj2 = {a: 2, b: 2}
        var copyObj = deepCopy(obj2)
        console.log(obj2);
        console.log(copyObj);
   // 方法缺点, 当值为undefined、function、symbol 会在转换过程中被忽略

使用slice的方式

let arr = [1,2,3,4]
let arr1 = arr.slice()

使用ES6 扩展运算符的方式

let arr = [1,2,3,4]
let [a,b,c,d] = [...arr]

使用Object.assign()的方式

let obj = {
  a: 1,
  b: 2,
}
let copyObj = Object.assign({},obj)
copyObj.a = 3;
obj.a // 1
copyObj.a // 3

使用jQuery的方式

var arr = [1,2,3,4]
var newArr = $.extend(true,[],arr)  //true则为深拷贝 false为浅拷贝

进阶版

      const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)
        const deepClone = function (obj, hash = new WeakMap()) {
            if (obj.constructor === Date)
                return new Date(obj)       // 日期对象直接返回一个新的日期对象
            if (obj.constructor === RegExp)
                return new RegExp(obj)     //正则对象直接返回一个新的正则对象
            //如果循环引用了就用 weakMap 来解决
            if (hash.has(obj)) return hash.get(obj)
            let allDesc = Object.getOwnPropertyDescriptors(obj)
            //遍历传入参数所有键的特性
            let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
            //继承原型链
            hash.set(obj, cloneObj)
            for (let key of Reflect.ownKeys(obj)) {
                cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
            }
            return cloneObj
        }


        let obj = {
            num: 0,
            str: '',
            boolean: true,
            unf: undefined,
            nul: null,
            obj: { name: '我是一个对象', id: 1 },
            arr: [0, 1, 2],
            func: function () { console.log('我是一个函数') },
            date: new Date(0),
            reg: new RegExp('/我是一个正则/ig'),
            [Symbol('1')]: 1,
        };
        Object.defineProperty(obj, 'innumerable', {
            enumerable: false, value: '不可枚举属性'
        }
        );
        obj = Object.create(obj, Object.getOwnPropertyDescriptors(obj))
        obj.loop = obj    // 设置loop成循环引用的属性
        let cloneObj = deepClone(obj)
        cloneObj.arr.push(4)
        console.log('obj', obj)
        console.log('cloneObj', cloneObj)