constdeepClone = a => { if (a instanceofObject) { // 判断类型(不考虑 iframe let result // 拷贝的结果 if (a instanceofFunction) { // 如果是函数,则需要判断普通函数和箭头函数 if (a.prototype) { // 有 prototype 则是普通函数,则返回一个函数 // 传 this 给我,我就传 this 给 a,传什么参数给我,我就传什么参数给 a,然后把 a 的返回值作为我的返回值 // 这样我的输入和输出和 a 一模一样,所以我是 a 的深拷贝 result = function () { return a.apply(this, arguments) } } else { // 如果是箭头函数,则返回一个箭头函数, // 传给我什么参数,我就把什么参数传给 a,箭头函数没有 this,则返回undefined,把 a 的返回值作为我的返回值 result = (...args) => { return a.call(undefined, ...args) } } } elseif (a instanceofArray) { // 如果是数组,则返回一个空数组 // 数组的内容由下面递归拷贝 result = [] } elseif (a instanceofDate) { // 如果是日期,则返回一个Date // 日期的内容为传给我的时间戳(把日期减0就会得到数字,这个数字是时间戳)或者 ISO 8601 字符串 result = newDate(a - 0) } elseif (a instanceofRegExp) { // 如果是正则,则返回一个正则 // 正则的内容为传给我的 source 和 flags result = newRegExp(a.source, a.flags) } else { // 其他的则是普通对象,则返回一个空对象 // 对象内容有下面递归拷贝 result = {} } for (let key in a) { // 递归:把 a 的所有子属性再深拷贝一遍 result[key] = deepClone(a[key]) } return result } else { // 不是对象则是:string number bool null undefined symbol bigint // 则直接返回 a return a } }
const cache = newMap() // 定义缓存 constdeepClone = a => { // 在深拷贝的时候检查一下 if (cache.get(a)) { // 如果发现 a 已经存在 // 就直接返回已经被我拷贝的东西 return cache.get(a) } if (a instanceofObject) { let result if (a instanceofFunction) { if (a.prototype) { result = function () { return a.apply(this, arguments) } } else { result = (...args) => { return a.call(undefined, ...args) } } } elseif (a instanceofArray) { result = [] } elseif (a instanceofDate) { result = newDate(a - 0) } elseif (a instanceofRegExp) { result = newRegExp(a.source, a.flags) } else { result = {} } // 构造出 result 之后往 cache 放东西 cache.set(a, result) for (let key in a) { result[key] = deepClone(a[key]) } return result } else { return a } }
写的不错,请问还有什么问题? 请看下面
不拷贝原型
我们在遍历 a 的时候,不能什么都遍历,有些属性是继承得到的,如果是继承得到的,我们不应该去深拷贝它
const cache = newMap() constdeepClone = a => { if (cache.get(a)) { return cache.get(a) } if (a instanceofObject) { let result if (a instanceofFunction) { if (a.prototype) { result = function () { return a.apply(this, arguments) } } else { result = (...args) => { return a.call(undefined, ...args) } } } elseif (a instanceofArray) { result = [] } elseif (a instanceofDate) { result = newDate(a - 0) } elseif (a instanceofRegExp) { result = newRegExp(a.source, a.flags) } else { result = {} } cache.set(a, result) // 细节在这里,我们在遍历 a 的时候,不能什么都遍历,有些属性是继承得到的,如果是继承得到的,我们不应该去深拷贝它 for (let key in a) { // 如果 key 在 a 的身上,我才会拷贝到 result,如果不在,则是在原型,在原型上我就不拷贝 if (a.hasOwnProperty(key)) { result[key] = deepClone(a[key]) } } return result } else { return a } }