美文网首页
JS基础心法-深浅拷贝

JS基础心法-深浅拷贝

作者: 付出的前端路 | 来源:发表于2018-07-25 12:24 被阅读0次

一、复制

浅拷贝

浅拷贝的意思就是只复制引用,而未复制真正的值。

// 数组
const originArr = [1, 2, 3]
const cloneArr = originArr
cloneArr[0] = 'a'
console.log(cloneArr) // [a, 2, 3]
// 原先的数组也改变了
console.log(originArr)// [a, 2, 3,]
// 指向的内存是一样的,所以返回true
console.log(cloneArr === originArr) // true

// 对象
const originObj = {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
const cloneObj = originObj;
cloneObj.a = {aa:'aa'};
console.log(cloneObj); // {a:{aa:'aa'},b:'b',c:Array[3],d:{dd:'dd'}}
console.log(originObj); // {a:{aa:'aa'},b:'b',c:Array[3],d:{dd:'dd'}}
console.log(cloneObj === originObj) // true

上面的代码是最简单的利用 = 赋值操作符实现了一个浅拷贝,可以很清楚的看到,随着 cloneArray 和 cloneObj 改变,originArray 和 originObj 也随着发生了变化。

深拷贝

深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制了一层引用,就连值也都复制了。
只要进行了深拷贝,它们老死不相往来,谁也不会影响谁。

目前实现深拷贝的方法不多,主要是两种方法:

1.JSON.stringify/parse的方法

利用 JSON 对象中的 parse 和 stringify

适用的情况,代码示例如下:

const originArr = [1, 2, 3]
const cloneArr = JSON.parse(JSON.stringify(originArr));
cloneArr[0] = 'a'
console.log(cloneArr) // [a, 2, 3]
// 原先的数组没有改变
console.log(originArr)// [1, 2, 3,]
// 指向的内存改变了,所以返回false
console.log(cloneArr === originArr) // false

不适用的情况,代码示例如下:

// 数组
const originArr = [1, 2, undefined]
const cloneArr = JSON.parse(JSON.stringify(originArr));
cloneArr[0] = 'a'

console.log(originArr)// [1, 2, undefined]
// 复制的数组属性丢失,为null
console.log(cloneArr) // [a, 2, null]

// 对象
const originObj = {
  name:'axuebin',
  sayHello:function(){
    console.log('Hello World');
  }
}

console.log(originObj); // {name: "axuebin", sayHello: ƒ}
const cloneObj = JSON.parse(JSON.stringify(originObj));
// 复制的对象属性丢失
console.log(cloneObj); // {name: "axuebin"}

以上代码显示,如果属性里面有undefined、function、symbol就不适用了

MDN给出的原因解释:

undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时

2.递归的方法

递归的思想就很简单了,就是对每一层的数据都实现一次 创建对象->对象赋值 的操作,简单粗暴上代码:

function deepClone(source){
  const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
  for(let keys in source){ // 遍历目标
    if(source.hasOwnProperty(keys)){
      if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接赋值
        targetObj[keys] = source[keys];
      }
    } 
  }
  return targetObj;
}

// ES6深度复制的递归方法
const deepClone = obj => {
  let clone = Object.assign({}, obj);
  Object.keys(clone).forEach(
    key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
  );
  return clone;
};

一般的:

const originObj = {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
const cloneObj = deepClone(originObj);
console.log(cloneObj === originObj); // false

cloneObj.a = 'aa';
cloneObj.c = [1,1,1];
cloneObj.d.dd = 'doubled';

console.log(cloneObj); // {a:'aa',b:'b',c:[1,1,1],d:{dd:'doubled'}};
console.log(originObj); // {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};

带有函数的:

const originObj = {
  name:'axuebin',
  sayHello:function(){
    console.log('Hello World');
  }
}
console.log(originObj); // {name: "axuebin", sayHello: ƒ}
const cloneObj = deepClone(originObj);
console.log(cloneObj); // {name: "axuebin", sayHello: ƒ}

也可以。搞定。

是不是以为这样就完了?? 当然不是。请看下篇深浅拷贝拓展

相关文章

  • JS文集的目录

    js基础心法 深浅拷贝(递归)深浅拷贝(首层浅拷贝) js 数据处理 数组对象查找的常见操作数组对象去重的常见操作...

  • JS基础心法-深浅拷贝

    一、复制 浅拷贝 浅拷贝的意思就是只复制引用,而未复制真正的值。 上面的代码是最简单的利用 = 赋值操作符实现了一...

  • JS基础心法-深浅拷贝(首层浅拷贝)

    我们知道在 JavaScript 中,数组有两个方法 concat 和 slice 是可以实现对原数组的拷贝的,这...

  • js的深浅拷贝

    js的深浅拷贝可以分为数组的深浅拷贝和对象的深浅拷贝 一、数组的深浅拷贝如果只是简单的将数组中的元素付给另外一个数...

  • js深浅拷贝

    项目中,一般会用loadsh库,地址:https://github.com/lodash/lodash 浅拷贝方法...

  • js 深浅拷贝

    浅拷贝 是 把对象或者数组的第一层 key 或者 索引 赋到 新的 对象或者对象上 深拷贝是迭代浅拷贝的操作,也就...

  • js 深浅拷贝

    深拷贝 更好的写法: 浅拷贝 浅拷贝,还可以用 Object.assign 、展开运算符 ...

  • JS深浅拷贝

  • JS深浅拷贝

    JS存储方式 JS中存在基本数据类型和引用数据类型1.基本数据类型:number,string,boolean,n...

  • JS深浅拷贝

    浅拷贝 浅拷贝的意思就是只复制引用,而未复制真正的值。 深拷贝 深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制...

网友评论

      本文标题:JS基础心法-深浅拷贝

      本文链接:https://www.haomeiwen.com/subject/xqlpmftx.html