数据浅克隆
// Object.assign()=>用于将所有可枚举属性的值从一个或多个原对象复制到目标对象中,然后返回目标对象
// 语法:Object.assign(target,...sources)【target:目标对象】,【sources:原对象(多个参数)】
// 例子:
let obj1={
a:1,
b:2,
c:3
};
let obj = Object.assign({},obj1,{d:4,e:5})
console.log(obj); //{a: 1, b: 2, c: 3, d: 4, e: 5}
// 例子2:如果是字符串将自动被转为对象,其他会被忽略
const v1='abc';
const obj=Object.assign({},v1);
console.log(obj);// { "0": "a", "1": "b", "2": "c" }
const v2 = true;
const v3 = 10;
const v4 = undefined;
const v5 = null;
const obj1 = Object.assign({}, v1,v2,v3,v4);
console.log(obj1); // { "0": "a", "1": "b", "2": "c" }
// 克隆整个函数
function shallowClone(a){
const obj={};//定义一个空对象储存每个数据,不允许再次修改
for(let i in a){
obj[i]=a[i];
}
return obj;
}
// 被克隆的对象
const oldObj={
a:1,
b:['1','2','3'],
c:{
d:{i:2}//新对象修改的属性值也会影响到被克隆对象相应的属性值
}
};
const newObj = shallowClone(oldObj);//将克隆出来的新对象地址指向被克隆的对象地址
console.log(newObj.c.d,oldObj.c.d);
console.log(oldObj.c.d===newObj.c.d);//true
数据浅克隆带来的影响:因为对象只会被克隆到最外部的一层,要克隆更深层的对象,则仍然是通过引用指向同一块堆内存
简而言之,当我对克隆出的对象做修改时,也会影响到被克隆的对象=>占用了不必要的内存空间(内存泄漏)
数据深克隆
// JOSN.parse(text,reviver)
// text:必选参数,一个有效的JS字符串;
// reviver:可选参数,一个转换结果的函数。如果成员包含嵌套对象,则先于父对象转换嵌套对象。对于每个成员,会发生以下情况:
// 1.如果reviver返回一个有效值,则成员值将替换为转换后的值
// 2.如果reviver返回它接收的相同值,则不修改成员值
// 3.如果reviver返回null或undefined,则删除成员
// 返回值:一个对象或数组
// 注意:
// 1.属性名必需是双引号括起来的字符串,最后一个属性后不能有逗号。
// 2.数值禁止出现前导零 (JSON.stringify 方法自动忽略前导零,而在 JSON.parse 方法中将会抛出 SyntaxError)。
// 3.只有有限的一些字符可能会被转义;禁止某些控制字符;Unicode行分隔符(U+2028)和段分隔符(U+2029)被允许;字符串必需用双引号括起来。
// SON.stringify()
// JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
// 语法:JSON.stringify(value[, replacer[, space]])
// value:必需, 要转换的 JavaScript 值(通常为对象或数组)。
// replacer:可选。用于转换结果的函数或数组。
// 如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。
// 如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。
// space:可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。
// 例题:JSON序列化方法
const oldObj = {
a: 1,
b: ['1', '2', '3'],
c: {
d: {
i: 2
}
}
};
const newObj = JSON.parse(JSON.stringify(oldObj));
console.log(newObj.c.d, oldObj.c.d); //{i:2}{i:2}
console.log(newObj.c.d === oldObj.c.d); //false
newObj.c.d.i = 'change';
console.log(newObj.c.d, oldObj.c.d); //{i:'change'}{i:2}
JSON.parse()的坑:
1.无法实现对函数、RegExp、稀疏数组等特殊对象的克隆
2.会抛弃对象的constructor,所有的构造函数都会指向Object原型
3.对象有循环引用时就会报错
// 例题2:
// hasOwnProperty()
// 定义:用于检测对象是否包含某些属性的方法,返回一个布尔值
let data1 = {c:1,d:2,f:{e:{i:2}}}
// 定义一个函数用来判断克隆的对象的数据类型是否符合
function isArray(arr){
return Object.prototype.toString.call(arr)==='[object Array]'
}
function deepClone(obj){
// 如果obj是原始数据类型就直接返回
if(typeof obj !== 'object'&& typeof obj !== 'function'){
return obj;
}
var a = isArray(obj)?[]:{};//判断obj的原型是否指向数组类型
for(i in obj){
// 判断obj对象师傅包含[i]属性
if(obj.hasOwnProperty(i)){
// 检测obj原型的[i]属性是否是一个对象类型
a[i]=typeof obj[i] === 'object'?deepClone(obj[i]):obj[i];
}
}
return a;
}
let data1Clone=deepClone(data1);
console.log(data1,data1Clone);
console.log(data1Clone.f.e===data1.f.e);//false
data1Clone.f.e.i='change';
console.log(data1Clone.f.e,data1.f.e);//{i:'change'}{i:2}