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,正則,函數沒法拷貝,時間會字符串化
相關文章
相關標籤/搜索