JavaScript对象特性-拷贝

244 阅读2分钟

javascript对象拷贝

javascript克隆一个对象时,为什么改变复制过来的变量,为何被克隆对象的值也随之改变?

答案其实很简单,这是因为javascript对象的变量实际上只是一个指针,它指向内存中的对象存储位置。

当我们仅仅通过 var a = b // b为被拷贝对象 的方式去拷贝对象时,只能拷贝该对象的指针,相当于有两个指针指向内存中同一个位置。

什么是浅拷贝?

只遍历对象的第一层属性和值。当如果拷贝的值也为对象时,实际上只拷贝了这个值的指针,这个指针仍然指向原对象。

有哪些方式?

  • object.asign({}, target);
  • for in 一层遍历对象的属性和值
  • Object.keys() 遍历属性
  • object.entries() 遍历属性
  • object.getOwnPropertyNames() 遍历属性

如何深拷贝对象?

  1. 可以采用序列化对象再反序列化回来。 这样做的弊端是,一些不可序列化的类型如日期类型,JSON.parse只会把它们当成字符串,而不是日期类型。

JSON.stringfy 不可转换的js属性

  • undefined // 无
  • function // 无
  • regExp(转换后变成了空对象)
  • Date(转换后变成了字符串,而非Date类的对象,JSON.parse只会把它们当成字符串,而不是日期类型。 )
  • Symbol // 无
  • 无法转换循环引用的对象
  1. 结构化克隆--html5的新算法 但是目前还不支持有些内置类型,但相比JSON.parse,他支持的类型要多得多,如:日期类型,Map, 正则表达式,集合,二进制大对象。

  2. 递归拷贝

var a = {a: 1,b: 2, c: 3, d: {a:1, b:2, c: 3}};
function deepClone(arr) {
   if(arr.constructor !== Array || arr.constructor !== Object) return arr;
   var clone = Array.isArray(arr) ? [] : {};
    for(let key of arr.keys()) {
        if(!isArray(arr[key])) {
             deepClone(arr[key]);
        } else if(arr[key].constructor === Object) {
            deepClone(arr[key]);
        } else {
           clone[key] = arr[key];
        }
    }
    return clone;
}

const ca = deepclone(a);

总结

浅拷贝和深拷贝取决于项目需要,一个对象的不同的拷贝方式,会产生不一样的效果。