- 我在工作中发现,由于某些原因,后台给的数据可能无法满足前端组件的需求,比如某个树形组件,我需要的数据格式为
data: {
value: 1,
label: "水果",
children: [
{
value: 2,
label: "苹果"
},
{
value: 3,
label: "橘子"
}
]
},
- 而后台给的数据格式为,值不同,字段名也不同
obj: {
id: 1,
name: "水果&fruit",
childlist: [
{
id: 2,
name: "苹果&apple"
},
{
id: 3,
name: "橘子&orange"
}
]
},
- 我不想改变原数据,希望 新拷贝一份数据 并 新增部分属性,此外再 将原属性值进行改进后再重新存储,我就可以这么做,说明见注释:
deepClone(obj, {
id: "value", // 将原对象 id 的属性值克隆到新对象 value 属性上
name: function(val) { // 将原对象的 name 属性值经过处理后,克隆到新对象的 label 属性上,函数参数 val 是原对象 name 属性的值
return {
label: val.split("&")[0]
};
},
childlist: "children"
});
-
克隆结果如下:
深拷贝源代码如下:
/**
* @description: 检测类型
* @param {any} o
* @return: Object,Array,Null,Number...
*/
function getType(o) {
let type = Object.prototype.toString.call(o);
type = type.slice(8, -1)
return type
}
/**
* @description: 深拷贝
* @param {any} o:拷贝源
* @param {object} option:
* 分两种情况:
* 1.{ 拷贝源属性A : 新对象属性B } : 将A对应的值拷贝到B上
* 2.{
* 拷贝源属性A : function(A对应的值) {
* 处理A...
* return {
* C:处理后的A
* }
* }
* }
* 可以将A对应的值进行处理,再放到新对象的C属性上(C与A平级)
* demo:
* cloneObj = deepClone(obj,
* {
* a: function(val) {
* return {
* newProp1: val,
* newProp2: val + 12
* };
* }
* }
* );
* @return: 深拷贝后的新对象
*/
function deepClone(o, option) {
let newObj;
if (getType(o) === "Array") {
newObj = []
} else if (getType(o) === "Object") {
newObj = {}
} else {
newObj = o
return newObj
}
// 循环拷贝源
for (let name in o) {
newObj[name] = deepClone(o[name], option)
// 循环配置对象
for (let oldProp in option) {
if (oldProp === name) {
// 如果配置对象的某个属性值不是函数,则符合情况1
if (getType(option[oldProp]) !== "Function") {
newObj[option[oldProp]] = deepClone(o[name], option)
}
// 如果配置对象的某个值是函数,则符合情况2。将函数返回值与新对象合并
else {
let rtn = option[oldProp](o[oldProp])
Object.assign(newObj, rtn)
}
}
}
}
return newObj
}
export { deepClone }
2019年2月7日改进
- 不传
option
参数时,直接拷贝 - 现在返回的克隆对象中不再含有 被拷贝的原属性
/**
* @description: 检测类型
* @param {any} o
* @return: Object,Array,Null,Number...
*/
function getType(o) {
let type = Object.prototype.toString.call(o);
type = type.slice(8, -1)
return type
}
/**
* @description: 深拷贝
* @param {any} o:拷贝源
* @param {object} option:
* 分两种情况:
* 1.{ 拷贝源属性A : 新对象属性B } : 将A对应的值拷贝到B上
* 2.{
* 拷贝源属性A : function(A对应的值) {
* 处理A...
* return {
* C:处理后的A
* }
* }
* }
* 可以将A对应的值进行处理,再放到新对象的C属性上(C与A平级)
* demo:
* cloneObj = deepClone(obj,
* {
* a: function(val) {
* return {
* newProp1: val,
* newProp2: val + 12
* };
* }
* }
* );
* @return: 深拷贝后的新对象
*/
function deepClone(o, option) {
let newObj;
if (getType(o) === "Array") {
newObj = []
} else if (getType(o) === "Object") {
newObj = {}
} else {
newObj = o
return newObj
}
// 循环拷贝源
for (let name in o) {
// 不传 option 参数时,直接克隆
if (getType(option) === "Undefined") {
newObj[name] = deepClone(o[name], option)
continue;
}
// 传递了 option 参数,循环配置对象
for (let oldProp in option) {
// 处理 option 中指定的原对象的属性
if (oldProp === name) {
// 如果配置对象的某个属性值不是函数,则符合情况1
if (getType(option[oldProp]) !== "Function") {
newObj[option[oldProp]] = deepClone(o[name], option)
}
// 如果配置对象的某个值是函数,则符合情况2。将函数返回值与新对象合并
else {
let rtn = option[oldProp](o[oldProp])
Object.assign(newObj, rtn)
}
}
// 其他未在 option 中指定的属性则直接拷贝
else {
newObj[name] = deepClone(o[name], option)
}
}
}
return newObj
}
export { deepClone }
2019年5月23日改进
- 修复
option
传入两个参数时,本应被删除的原属性重新出现 -
option
传入函数时,参数值添加了一个当前对象
/**
* @description: 检测类型
* @param {any} o
* @return: Object,Array,Null,Number...
*/
function getType(o) {
let type = Object.prototype.toString.call(o);
type = type.slice(8, -1)
return type
}
/**
* @description: 深拷贝
* @param {any} o:拷贝源
* @param {object} option:
* 分两种情况:
* 1.{ 拷贝源属性 A : 新对象属性 B } : 将 A 对应的值拷贝到 B 上
* 2.{
* 拷贝源属性A : function(A 对应的值, A 所在的整个对象) {
* 处理A...
* return {
* C:处理后的A
* }
* }
* }
* 可以将A对应的值进行处理,再放到新对象的C属性上(C与A平级)
* demo:
* cloneObj = deepClone(obj,
* {
* a: function(val) {
* return {
* newProp1: val,
* newProp2: val + 12
* };
* }
* }
* );
* @return: 深拷贝后的新对象
*/
function deepClone(o, option) {
let newObj;
if (getType(o) === "Array") {
newObj = []
} else if (getType(o) === "Object") {
newObj = {}
} else {
newObj = o
return newObj
}
// 循环拷贝源
for (let name in o) {
// 不传 option 参数时,直接克隆
if (getType(option) === "Undefined") {
newObj[name] = deepClone(o[name], option)
continue;
}
// 标识 option 中指定的参数是否存在于拷贝源
let exist = false
// 传递了 option 参数,循环配置对象
for (let oldProp in option) {
// 处理 option 中指定的原对象的属性
if (oldProp === name) {
exist = true
// 如果配置对象的某个属性值不是函数,则符合情况1
if (getType(option[oldProp]) !== "Function") {
newObj[option[oldProp]] = deepClone(o[name], option)
}
// 如果配置对象的某个值是函数,则符合情况2。将函数返回值与新对象合并
else {
let rtn = option[oldProp](o[oldProp], o)
Object.assign(newObj, rtn)
}
}
}
// 其他未在 option 中指定的属性则直接拷贝
if (!exist) {
newObj[name] = deepClone(o[name], option)
}
}
return newObj
}
export { deepClone }