JS深浅拷贝

前言

做为面试必问的题目之一,看似简单的问题,有不少细节有时候仍是很难注意到。此次对JS的深拷贝与浅拷贝作一个总结。面试

概念

浅拷贝:拷贝对象第一层基本数据类型数据,如有子对象,则拷贝子对象地址,操做子对象时互有影响**数组

深拷贝:彻底拷贝对象,对两个对象进行操做时互不影响**bash

JS数据类型

  • 基本数据类型(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
}
复制代码

基本数据类型进行了值拷贝,而对象则拷贝了地址

Object.assign()

let des = Object.assign({},obj)
复制代码

拷贝目标对象全部可枚举属性,但为浅拷贝

Array.property.slice()

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)
复制代码

  • 提示:这种方式只对数组对象及基本数据类型有效,date、正则及函数,没法拷贝,均生成空对象

JSON.parse(JSON.stringify(obj))

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)
复制代码

  • 提示:一般状况下推荐这种方式深拷贝,能解决大多数问题。要注意的是,symbol,undifined,正则,函数没法拷贝,时间会字符串化
相关文章
相关标签/搜索