目录
1.7 如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象
1.10 直接使用var newObj = Object.create(oldObj)
浅拷贝
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
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.小结