前端队长の技术博客

  1. 背景
  2. 浅拷贝
    1. 对象的浅拷贝
    2. 数组的浅拷贝
  3. 深拷贝
  4. 参考文档

背景

踩过的坑如下:

formData本来是父组件传过来的,但是我不想直接用,于是我直接赋值给一个formDataCopy的对象。

但是诡异的事情发生了,就是在我填写自己的表单组件的时候,一旦表单的数据发生的变化时,本来是formDataCopy的值发生变化,但是‘formDataDefault值’ 这个字符串却被打印出来,也就是说formData改变了。

奇怪,formData是父组件传过来的值怎么会改变呢?

经过一番挣扎,才发现formDataCopy使用的是简单的赋值,导致formDataCopy和formData指向相同的对象。

formDataCopy一改变,formData就会跟着变。

以上是背景,所以我就对浅拷贝和深拷贝进行了总结:

浅拷贝

什么是浅拷贝:两者是指向一个对象。

对象的浅拷贝

1、对象的直接遍历赋值。(for..in..)

2、ES6中的 var copyObj = Object.assign({}, obj);

Object.assign注意事项

3、ES7扩展运算符 var copyObj = { ...obj }

4、Jquery浅拷贝 var copiedObject = jQuery.extend({}, originalObject) 如果改变了originalObject,copiedObject 也会变。

5、第三方js库:Lodash.clone函数

数组的浅拷贝

(两者指向不同的对象,但是只能拷贝一层)

如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变,所以是浅拷贝。

对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

也就是说,如果原数组改变的是基本数据类型,比如String,Boolean,Number的数据,不会影响到新数组; 但是如果改变的是对象或者数组中的数据,是会影响到新数组的,也也就是对于对象或者数组,新旧数组指向的是一个对象。

深拷贝

(下面说的深拷贝是基本对象的深拷贝,不考虑对象的复杂属性,比如set,get,Function等)

1、最简单的方式 JSON.parse(JSON.stringify(Obj)) 这种方法使用较为简单,可以满足基本的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。因为这两者基于JSON.stringify和JSON.parse处理后,得到的正则就不再是正则(变为空对象),得到的函数就不再是函数(变为null)了。

2、jQuery深拷贝 var copiedObject = $.extend(true, {}, originalObject)

3、手动写递归方式 原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。

var array = [
   { number: 1 },
   { number: 2 },
   { number: 3 }
];
function copy (obj) {
    var newobj = obj.constructor === Array ? [] : {};
    if(typeof obj !== 'object'){
        return;
    }
    for(var i in obj){
       newobj[i] = typeof obj[i] === 'object' ? copy(obj[i]) : obj[i];
    }
    return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); //  [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]

4、第三方js库:Lodash.cloneDeep 函数

参考文档

https://www.cnblogs.com/penghuwan/p/7359026.html

https://github.com/wengjq/Blog/issues/3

(完)