Fe-interview: [js] 第351天 请写一个性能最好的深度克隆对象的方法

Created on 31 Mar 2020  ·  8Comments  ·  Source: haizlin/fe-interview

第351天 请写一个性能最好的深度克隆对象的方法

167

我也要出题

js

Most helpful comment

那就写个递归吧:

const deepClone = (obj) => {
  const copy = obj instance Array ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
       copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
   }
  }
return copy;
}

typeof obj[key] === 'object' 有大坑,比如 null

All 8 comments

如果不使用 Date , 函数, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, 稀疏数组(sparse Arrays), 类型数组(Typed Arrays)或者其他复杂类型,那么简单又快的深拷贝:
JSON.parse(JSON.stringify(object))

ES6
使用es6扩展运算符进行克隆
var A1 = {a: "2"}; var A2 = Object.assign({}, A1); var A3 = {...A1}; // Spread Syntax

参考文档 What is the most efficient way to deep clone an object in JavaScript?

如果不使用 Date , 函数, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, 稀疏数组(sparse Arrays), 类型数组(Typed Arrays)或者其他复杂类型,那么简单又快的深拷贝:
JSON.parse(JSON.stringify(object))

ES6
使用es6扩展运算符进行克隆
var A1 = {a: "2"}; var A2 = Object.assign({}, A1); var A3 = {...A1}; // Spread Syntax

参考文档 What is the most efficient way to deep clone an object in JavaScript?

补充一下
ES6的Object.assign,和扩展运算符都是一层浅拷贝,测试过了,JSON.parse对循环引用也无能为力。
复杂结构深拷贝参考https://www.jianshu.com/p/f5f8e4858b9b
总的来说最不济就是写递归判断每一项类型去做不同的操作,其他官方API还不算是很友好。

楼上说的递归

const deepClone = obj => {
let cloneObj = {};
for (let key in obj) {
if (typeof obj[key] === "object" && typeof obj[key] !== "null") {
cloneObj[key] = deepClone(obj[key]);
} else {
cloneObj[key] = obj[key];
}
}
return cloneObj;
};

var personalDetail = {
name: "Nishant",
address: {
location: "xyz",
zip: "123456",
phoneNumber: {
homePhone: 8797912345,
workPhone: 1234509876
}
}
};

console.log(deepClone(personalDetail));

time complexity: O(n)

那就写个递归吧:

const deepClone = (obj) => {
  const copy = obj instance Array ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
       copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
   }
  }
return copy;
}

那就写个递归吧:

const deepClone = (obj) => {
  const copy = obj instance Array ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
       copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
   }
  }
return copy;
}

typeof obj[key] === 'object' 有大坑,比如 null

谢谢提醒~

那就写个递归吧:

const deepClone = (obj) => {
  const copy = obj instance Array ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
       copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
   }
  }
return copy;
}

typeof obj[key] === 'object' 有大坑,比如 null

const deepClone = (obj) => {
  let copy = obj instanceof Array ? [] : {}
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = Object.prototype.toString().call(obj[key]) === ['object Object'] ||  Object.prototype.toString().call(obj[key]) === ['object Array']? deepClone(obj[key]) : obj[key]
    }
  }
}

这里做一下调整怎么样?

function objectDeepClone1(obj) {
    return JSON.parse(JSON.stringify(obj))
}

function objectDeepClone2(obj) {
    let type = Object.prototype.toString.call(obj);
    let newObject = new Object();
    let newArray = new Array();
    if (type.substring(8, type.length - 1) === 'Object') {
        for (let key in obj) {
            let type2 = Object.prototype.toString.call(obj[key]);
            if (type2.substring(8, type2.length - 1) === 'Object') {
                newObject[key] = objectDeepClone2(obj[key])
            } else if (type2.substring(8, type2.length - 1) === 'Array') {
                let newArray = new Array();
                obj[key].forEach((item) => {
                    newArray.push(objectDeepClone2(item))
                })
                newObject[key] = newArray
            } else {
                newObject[key] = obj[key]
            }
        }
        return newObject;
    } else if (type.substring(8, type.length - 1) === 'Array') {
        obj.forEach((item) => {
            newArray.push(objectDeepClone2(item))
        })
        return newArray;
    }
}

console.time('深度克隆1')
let cityInfo1 = objectDeepClone1(cityInfo)
console.log('深度克隆后的cityInfo1', cityInfo1);
console.timeEnd('深度克隆1')
console.time('深度克隆2')
let cityInfo2 = objectDeepClone2(cityInfo)
console.log('深度克隆后的cityInfo2', cityInfo2);
console.timeEnd('深度克隆2')

其中通过JSON.stringfy序列化实现对象深度复制花费时间更短。

Was this page helpful?
0 / 5 - 0 ratings