这类题目的发问方式又很多,除了“模拟 JAVA 中的克隆接口”、“JavaScript 实现原型模式”以外,它更常见、更友好的发问形式是“请实现JS中的深拷贝”。
实现 JavaScript 中的深拷贝,有一种非常取巧的方式 —— JSON.stringify:
const liLei = {
name: 'lilei',
age: 28,
habits: ['coding', 'hiking', 'running']
}
const liLeiStr = JSON.stringify(liLei)
const liLeiCopy = JSON.parse(liLeiStr)
liLeiCopy.habits.splice(0, 1)
console.log('李雷副本的habits数组是', liLeiCopy.habits)
console.log('李雷的habits数组是', liLei.habits)
但是注意,这个方法存在一些局限性,比如无法处理 function、无法处理正则等等——只有当你的对象是一个严格的 JSON 对象时,可以顺利使用这个方法。在面试过程中,大家答出这个答案没有任何问题,但不要仅仅答这一种做法。
深拷贝没有完美方案,每一种方案都有它的边界 case。而面试官向你发问也并非是要求你破解人类未解之谜,多数情况下,他只是希望考查你对递归的熟练程度。所以递归实现深拷贝的核心思路,大家需要重点掌握(解析在注释里):
function deepClone(obj) {
// 如果是 值类型 或 null,则直接return
if(typeof obj !== 'object' || obj === null) {
return obj
}
// 定义结果对象
let copy = {}
// 如果对象是数组,则定义结果数组
if(obj.constructor === Array) {
copy = []
}
// 遍历对象的key
for(let key in obj) {
// 如果key是对象的自有属性
if(obj.hasOwnProperty(key)) {
// 递归调用深拷贝方法
copy[key] = deepClone(obj[key])
}
}
return copy
}
调用深拷贝方法,若属性为值类型,则直接返回;若属性为引用类型,则递归遍历。这就是我们在解这一类题时的核心的方法。