JS深淺拷貝

1. 前言

1.很早之前寫了純文本的深淺拷貝

  1. 好不容易有空 改個 markdown版本的

2. 是什么 what

深淺拷貝理解,拷貝就是復(fù)制,js對引用類型數(shù)據(jù)的數(shù)據(jù)拷貝

淺拷貝 :由于引用類型數(shù)據(jù)是存在堆內(nèi)存中,堆內(nèi)存中存放的是引用類型的值,同時引用數(shù)據(jù)有會指針指向棧內(nèi)存,淺拷貝的指針指向棧內(nèi)存是一致的,所以一個改變另一個也會受影響。
深拷貝:是在堆內(nèi)存開啟新的空間存放數(shù)據(jù)。

簡單理解就是:
如果拷貝產(chǎn)生新的數(shù)據(jù)就是深拷貝,
如果只是數(shù)據(jù)的引用,就是淺拷貝


3. 應(yīng)用場景

  1. react redux
  2. table列表修改 彈出 表單
    editRow(rowData) {
      ElMessage.success("點擊了 編輯")
      console.log("編輯數(shù)據(jù):", rowData)
      this.editForm = rowData
      this.editDialog = true
    },
  1. 這里不使用深拷貝的話 diaog 隨便修改不進(jìn)行保存也影響 界面的數(shù)據(jù)

4. 第三方依賴

clone-deep


5. 栗子

let people = {name:'yzs',age:21,sex:true}

let obj = JSON.parse(JSON.stringify(test))

obj.name = 'yqq'

people.name  輸出 'yzs'

哈哈是不是 so easy But 也有弊端

  1. 無法復(fù)制函數(shù),正則
  2. 原型鏈沒了,對象就是object,所屬的類沒了
  3. 循環(huán)引用的問題,沒解決
  4. 當(dāng)然jQ 的 extend函數(shù)也可以實現(xiàn)深復(fù)制,但是我目前jQ基本不用了

6.淺復(fù)制代碼

let people = {name:'yzs', age:28}
// 調(diào)用
let shallowObj = shallowCopy(people)
// 方法
shallowCopy = (obj)=>{
      var temp = {}
      for (const prop in obj){
         if( Object.prototype.hasOwnProperty.call(obj,prop) ){
              temp[prop] = obj[prop]
          }
    }
  return temp
}

只復(fù)制一層對象的屬性,也就是說淺復(fù)制是對對象地址的復(fù)制,修改其中一個對象的屬性,則另一個對象的屬性也會隨之改變,這就導(dǎo)致people.name和shallowObj.name指向同一塊內(nèi)存地址

影響

shallowObj.name = 'yqq'
people.name   結(jié)果也是'yqq' 而不是原來的'yzs'

7.深復(fù)制代碼

let people = {name:'yzs', age:28}
// 調(diào)用
let shallowObj =deepCopy(people)
// 方法
deepCopy = oldObj=>{
    var newObj = newObj || {}
    for (const i in oldObj){
        if(typeof oldObj[i] ==='object'){
              if(oldObj[i] ===null){
                newObj[i] =null
              }else {
                if(oldObj[i].constructor === Array){
                newObj[i] = []
         }else {
            newObj[i] = {}
         }
    }
    deepCopy(oldObj[i],newObj[i])
}else{
    newObj[i] = oldObj[i]
   }
}
  return newObj
}

深復(fù)制會遞歸賦值對象所有層級,也就是說深復(fù)制會開辟新的棧,所以2個對象對象不同的地址,修改其中一個對象的屬性,不會改變另一個對象的屬性

不影響

shallowObj.name = 'yqq'

people.name   結(jié)果'yzs' 

8. 深拷貝的另類方式

  1. 將需要 深拷貝的 對象 進(jìn)行JSON.stringify()序列化
  2. 在進(jìn)行JSON.parse() 反序列化
  3. 缺點: 比如對象中不能存在循環(huán)引用

9. 數(shù)組

擴(kuò)展運算符

console.log(...[1, 2, 3])
// 1 2 3
console.log(...[1, [2, 3, 4], 5])
// 1 [2, 3, 4] 5

數(shù)組 api

  1. slice()

10. 對象淺拷貝

擴(kuò)展運算符

let outObj = {
  inObj: {a: 1, b: 2}
}
let newObj = {...outObj}
newObj.inObj.a = 2
console.log(outObj) // {inObj: {a: 2, b: 2}}

Object.assign()

let outObj2 = {
  inObj: {a: 1, b: 2}
}
let newObj = Object.assign({}, outObj2)
newObj.inObj.a = 2
console.log(outObj2) // {inObj: {a: 2, b: 2}}

  • 都是淺拷貝

Object.assign()方法接收的第一個參數(shù)作為目標(biāo)對象,后面的所有參數(shù)作為源對象。然后把所有的源對象合并到目標(biāo)對象中。它會修改了一個對象,因此會觸發(fā) ES6 setter。

擴(kuò)展操作符(…)使用它時,數(shù)組或?qū)ο笾械拿恳粋€值都會被拷貝到一個新的數(shù)組或?qū)ο笾?。它不?fù)制繼承的屬性或類的屬性,但是它會復(fù)制ES6的 symbols 屬性。


后記


初心

我所有的文章都只是基于入門,初步的了解;是自己的知識體系梳理,如有錯誤,道友們一起溝通交流;
如果能幫助到有緣人,非常的榮幸,一切為了部落的崛起;
共勉
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 淺拷貝 前面已經(jīng)提到,在定義一個對象或數(shù)組時,變量存放的往往只是一個地址。當(dāng)我們使用對象拷貝時,如果屬性是對象或數(shù)...
    泉泉泉泉泉泉閱讀 249評論 0 2
  • 引用類型 之所以會出現(xiàn)深淺拷貝的問題,實質(zhì)上是由于JS對基本類型和引用類型的處理不同?;绢愋椭傅氖呛唵蔚臄?shù)據(jù)段,...
    筆墨or小舟閱讀 772評論 0 0
  • JS存儲方式 JS中存在基本數(shù)據(jù)類型和引用數(shù)據(jù)類型1.基本數(shù)據(jù)類型:number,string,boolean,n...
    壹豪閱讀 398評論 0 0
  • 轉(zhuǎn)載于:https://www.cnblogs.com/136asdxxl/p/8645750.html 一、js...
    小鳳年閱讀 7,760評論 0 6
  • 對象類型在賦值的過程中其實是復(fù)制了地址,這樣會導(dǎo)致一方改變的時候其他地方也都會被改變的情況 例: 這種情況下我們就...
    王希桐閱讀 403評論 0 1

友情鏈接更多精彩內(nèi)容