快速复制对象/数组、深度冻结对象

21 篇文章 14 订阅

快速浅复制对象

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>

	<body>
	</body>
	<script>
//		快速复制一个对象:
		/**
		 * 方法一  将对象进行序列化,再进行反序列化从而赋值
		 * 缺点:丢失原对象的方法。(因为方法无法被序列化和反序列化)
		 * */
		function deepcopy01(obj) {
		    //如果传入的不是对象的话,也会默认为数组,否则下方发序列化就会报错
		    var newobj = obj.constructor === 'Object'?{}:[];  
			var s = JSON.stringify(obj);//系列化对象
			newobj = JSON.parse(s); //反系列化(还原)
			return newobj;
		}
		var cloneObj = deepcopy01(obj);
		console.log(cloneObj);
		
		/** 方法二  递归 **/
        function deepcopy02(obj){
		    let temp = null;
		    if(obj instanceof Array){
		        temp = obj.concat();
		    }else if(obj instanceof Function){
		        //函数是共享的是无所谓的,js也没有什么办法可以在定义后再修改函数内容
		        temp = obj;
		    }else{
		        temp = new Object();
		        for(let item in obj){
		            let val = obj[item];
		            temp[item] = typeof val == 'object'?deepcopy02(val):val; //这里也没有判断是否为函数,因为对于函数,我们将它和一般值一样处理
		        }
		    }
		    return temp;
		}
        
        var cloneObj02 = deepcopy02(obj);
        console.log(cloneObj02);
        
        
        /** 方法三  es6的assign方法,浅复制**/
        var cloneObj03 = Object.assign({},obj);
        console.log(cloneObj03);

        /** 方法四  es6的扩展运算符,浅复制**/
        var cloneObj4 = {...obj}      // 这种方法可以复制方法
        		
	</script>

</html>

快速深度复制数组

let  arr = [1,2,3];
//方法一   contact()方法 (数组合并法)(适用 单层 数组嵌套的深拷贝)
b=a.concat();

//方法二(es6的...)(适用 单层 数组嵌套的深拷贝)
let arr = [1,2,3],
newArr = [...arr];

let  test_arr = [{name:'cj',age:28},{name:'cj',age:28}]

//方法三   序列化(多层 数组嵌套的深拷贝)
let  copy_arr = JSON.parse(JSON.stringify(test_arr));

//方法四   遍历法(多层 数组嵌套的深拷贝)

深度遍历法

// 数据类型判断
function getType(obj){
	let type = Object.prototype.toString.call(obj).slice(8,-1);
	// 特殊情况,单独处理 ---- 在type为Number时,原数据obj可能是Number,也可能是NaN
	if(type === 'Number' && isNaN(obj)){
      return "NaN"
    }else{
	  return type
	}
}
// 实现方式
function deepClone2(target,visitedArr = []) {
	let clone = null;
	let type = getType(target)
	//对象、数据
	if(['Object','Array'].includes(type)) {   // 对象、数组的特殊处理
		if(visitedArr.includes(target)){  // 判断环状数据,防止爆栈
			clone = target
		}else{
			visitedArr.push(target)
			clone = Array.isArray(target) ? [] : {};
			for (const key in target) {
				clone[key] = deepClone2(target[key],visitedArr)
			}
		}
	}else if(type === 'Function'){   // 函数的特殊处理,如果不处理,结果新旧两个函数通过=== 对比,返回true
		clone = eval('(' + target.toString() + ')');
	}else{
		clone = target
	}
	return clone;
}

// 输入环状数据 --- 预期不爆栈且深度复制
let circleObj = {
  foo: {
    name: function() {
      console.log(1)
    },
	date: new Date(),
	reg: /\W/g,
    bar: {
	  und: undefined,
	  nul: null,
      name: 'bar',
      baz: {
        name: 'baz',
        aChild: null //待会让它指向obj.foo
      }
    }
  }
}
circleObj.foo.bar.baz.aChild = circleObj.foo  // 循环引用
var circleObjCopy = deepClone2(circleObj)
console.log(circleObjCopy, circleObj) // 测试通过
console.log('function---',circleObjCopy.foo.name === circleObj.foo.name) // 测试通过
console.log('object---',circleObjCopy.foo === circleObj.foo) // 测试通过

//序列化方法适用于Oject的深度拷贝,因为Array属于Oject类型,所以也适用于此处;
//需要注意的是:作为Oject的深度拷贝时,要复制的function会直接消失,所以这个方法只能用在单纯只有数据的对象。demo如下:

var obj = {
	name: 'cj',
	age: 28,
	add: function() {
		this.age += 1;
	}
}

var copy_obj = JSON.parse(JSON.stringify(obj));
copy_obj.name = 'cjj';
console.log('old');
console.log(obj);
console.log('copy');
console.log(copy_obj); //复制后add方法遗失

var arr = [{
		type: 1,
		func: function() {}
	},
	{
		type: 2,
		func: function() {}
	}
]
var copy_arr = JSON.parse(JSON.stringify(arr));
copy_arr[0].type = 111;
console.log('old');
console.log(arr);
console.log('copy');
console.log(copy_arr); //复制后func方法遗失

冻结对象(Object.freeze(对象))

没有深冻结
let person = {
    name: "Leonardo",
    profession: {
        name: "developer"
    }
};
Object.freeze(person);    // 冻结对象 ,如果对象的属性值也是一个对象,这里则无法冻结,所以这里并没有深度冻结
person.profession.name = "doctor";
console.log(person); //output { name: 'Leonardo', profession: { name: 'doctor' } }
深度冻结
//通过遍历,冻结所有属性值为对象的对象。
function deepFreeze(object) {
    let propNames = Object.getOwnPropertyNames(object);
    for (let name of propNames) {
        let value = object[name];
        object[name] = value && typeof value === "object" ? deepFreeze(value) : value;
    }
    return Object.freeze(object);
}
let person = {
    name: "Leonardo",
    profession: {
        name: "developer"
    }
};
deepFreeze(person);
person.profession.name = "doctor"; // TypeError: Cannot assign to read only 

参考页面 https://www.cnblogs.com/amiezhang/p/8023731.html
参考页面 https://blog.csdn.net/u010139505/article/details/52836102

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值