快速浅复制对象
<!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