做为面试必问的题目之一,看似简单的问题,有不少细节有时候仍是很难注意到。此次对JS的深拷贝与浅拷贝作一个总结。面试
浅拷贝:拷贝对象第一层基本数据类型数据,如有子对象,则拷贝子对象地址,操做子对象时互有影响**数组
深拷贝:彻底拷贝对象,对两个对象进行操做时互不影响**bash
基本数据类型(string,number,boolean,null,undifuned)函数
特性:原始值不可变,存放于栈中,当进行赋值操做时,生成的两个变量互不干扰ui
引用数据类型(对象,函数组等)spa
特性:值可变,存放于堆中,当进行赋值操做时,拷贝的是引用地址,两个地址指向同一对象,两个变量对这个对象都可操做(深浅拷贝均针对引用数据类型)code
定义cdn
将对象的第一层基本数据类型值进行拷贝,当碰见子对象时拷贝其地址。当对拷贝对象的基本数据类型属性值操做时,二者互不影响,而对拷贝对象的子对象进行操做时,原对象的子对象也会发生变化对象
实现blog
function shallowCopy(obj){
let des={}
for(let i in obj){
if(obj.hasOwnProperty(obj[i])){ //去除原型链属性
des[i]=obj[i]
}
}
return des
}
复制代码
基本数据类型进行了值拷贝,而对象则拷贝了地址
let des = Object.assign({},obj)
复制代码
拷贝目标对象全部可枚举属性,但为浅拷贝
let des = arr.slice()
复制代码
对数组进行拷贝,但为浅拷贝
let des = arr.concat()
复制代码
同上
定义
彻底拷贝目标对象,不管怎么操做拷贝对象,目标对象均不变化。二者互不影响
实现
递归拷贝
function isObj(obj){
return (typeof obj === 'object' || typeof obj === 'function') && obj != null
}
function deepClone(obj){
let des=Array.isArray(obj)?[]:{}
for(let i in obj){
des[i]=isObj(obj[i])?deepClone(obj[i]):obj[i]
}
return des
}
let a = {
name:'hkj',
obj:{
age:30
},
b:undefined,
c:Symbol(11),
arr:[1,2,3],
time:new Date(),
reg:/\d/,
fun:()=>{return}
}
let b=deepClone(a)
console.log(a)
console.log(b)
复制代码
let a = {
name:'hkj',
obj:{
age:30
},
b:undefined,
c:Symbol(11),
arr:[1,2,3],
time:new Date(),
reg:/\d/,
fun:()=>{return}
}
let b=JSON.parse(JSON.stringify(a))
console.log(a)
console.log(b)
复制代码