浅拷贝和深拷贝

目录

浅拷贝

1.对象拷贝 (李)

2.拷贝的其他方法

2.1 ES6 扩展运算符

2.2 Object.assign()

2.3 for...in 只循环第一层

2.4 直接用=赋值

3.练习

4.数组结构

5.对象结构

深拷贝

1.实现深拷贝

1.1采用递归去拷贝所有层级属性

1.2 通过JSON对象来实现深拷贝

1.3 通过jQuery的extend方法实现深拷贝

1.4 lodash函数库实现深拷贝

1.5 Reflect法

1.6 手动实现深拷贝

1.7 如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象

1.8 用slice实现对数组的深拷贝

1.9 用concat实现对数组的深拷贝

1.10 直接使用var newObj = Object.create(oldObj)

1.11 使用扩展运算符实现深拷贝

2.小结


浅拷贝

1.对象拷贝 (李)

 

2.拷贝的其他方法

2.1 ES6 扩展运算符

 

2.2 Object.assign()

var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3

2.3 for...in 只循环第一层

// 只复制第一层的浅拷贝
function simpleCopy(obj1) {
   var obj2 = Array.isArray(obj1) ? [] : {};
   for (let i in obj1) {
   obj2[i] = obj1[i];
  }
   return obj2;
}
var obj1 = {
   a: 1,
   b: 2,
   c: {
         d: 3
      }
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4

2.4 直接用=赋值

let a=[0,1,2,3,4],
    b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);

3.练习

需求:把数组拷贝一份,和原数组脱离关系

let arr = ['tom','anna'];
// 1. 创建一个新的数组brr
let brr = []

// 2. 遍历每一项arr,添加到brr中
for(let i=0;i<arr.length;i++){
    brr.push(arr[i])
}
arr.push('terry')
console.log(brr) //['tom','anna']

//总结:
拷贝:准备一个新的对象/数组,把旧的值复制过来
浅拷贝:只拷贝第一层的值

4.数组结构

浅拷贝只能拷贝第一层的值

 

5.对象结构

浅拷贝:只拷贝第一层值,第二层相互引用

 

深拷贝

1.实现深拷贝

1.1采用递归去拷贝所有层级属性

let oldObj = {
	name:'tom',
    age:18,
    grade:[100,99],
    family:{
        fName:'jack'
    }
}

//实现深拷贝
//注意:先写Array类型的判断(因为Array的父类是Object,写在上面无论是数组还是对象都会进去)
let newObj = {}
function deepClone(newO,oldO){  // {},oldObj{}
    for(let key in oldO){  //key:'name'->key:'age'->'grade'->family
        let value = oldO[key]  //'tom' -> 18 -> [100,99]->{fName:'jack'}
        if(value instanceof Array){
            newO[key] = []   //如果被拷贝的是数组,创建一个新的数组
            //1.新的数组 2.旧值  递归调用,再一次执行deepClone函数
            //此次递归遍历的是数组里的每一个值
            deepClone(newO[key],value)  //递归
            //deepClone(grade后[],[100,99]) 暂停for循环,先递归执行
            //{name:'tom',age:18,grade:[100,99]}
            //递归执行完之后,继续for循环
        }else if(value instanceof Object){
            newO[key] = {}   //被拷贝的是对象,创建一个新对象
            deepClone(newO[key],value)  //递归
            //{name:'tom',age:18,grade:[100,99],family:{fName:'jack'}}
        }else{
            newO[key] = value  //基础类型,单纯进行值的复制
            // {name:'tom',age:18}
        }
    }
}
deepClone(newObj,oldObj) //{name:'tom',age:18,grade:[100,99],family:{fName:'jack'}}
oldObj.grade.push(600)
console.log(newObj)  //新的对象里边没有添加600

//总结:深拷贝
递归每层引用类型,遇到对象/数组,创建一个新的,把基础值复制过来

1.2 通过JSON对象来实现深拷贝

function deepClone2(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}

缺点: 无法实现对对象中方法的深拷贝,会显示为undefined

1.3 通过jQuery的extend方法实现深拷贝

var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝

1.4 lodash函数库实现深拷贝

let result = _.cloneDeep(test)

1.5 Reflect法

// 代理法
function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一个对象!')
    }

    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [...obj] : { ...obj }
    Reflect.ownKeys(cloneObj).forEach(key => {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })

    return cloneObj
}

1.6 手动实现深拷贝

let obj1 = {
   a: 1,
   b: 2
}
let obj2 = {
   a: obj1.a,
   b: obj1.b
}
obj2.a = 3;
alert(obj1.a); // 1
alert(obj2.a); // 3

1.7 如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象

var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign({}, obj); // obj赋值给一个空{}
obj1.a = 3;
console.log(obj.a);// 1

img

 

1.8 用slice实现对数组的深拷贝

// 当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝
// 当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝
var arr1 = ["1","2","3"]; 
var arr2 = arr1.slice(0);
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );

1.9 用concat实现对数组的深拷贝

// 当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝
var arr1 = ["1","2","3"];
var arr2 = arr1.concat();
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );
// 当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝
var arr1 = [{a:1},{b:2},{c:3}];
var arr2 = arr1.concat();
arr2[0].a = "9";
console.log("数组的原始值:" + arr1[0].a ); // 数组的原始值:9
console.log("数组的新值:" + arr2[0].a ); // 数组的

1.10 直接使用var newObj = Object.create(oldObj)

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

1.11 使用扩展运算符实现深拷贝

// 当value是基本数据类型,比如String,Number,Boolean时,是可以使用拓展运算符进行深拷贝的
// 当value是引用类型的值,比如Object,Array,引用类型进行深拷贝也只是拷贝了引用地址,所以属于浅拷贝
var car = {brand: "BMW", price: "380000", length: "5米"}
var car1 = { ...car, price: "500000" }
console.log(car1); // { brand: "BMW", price: "500000", length: "5米" }
console.log(car); // { brand: "BMW", price: "380000", length: "5米" }

2.小结

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值