forEach在遍歷過程當中修改原數組的一些問題

咱們先來看下第一段代碼:數組

const arr1 = [
    { id: 1, value: 1 },
    { id: 2, value: 2 },
    { id: 3, value: 3 },
    { id: 4, value: 4 },
    { id: 5, value: 5 },
]
arr1.forEach((item, index) => {
    if (item.id === 1) {
        item.value *= 10
    }
})

將第一段代碼放入瀏覽器控制檯執行完以後,打印數組arr1瀏覽器

[
    0: {id: 1, value: 10}
    1: {id: 2, value: 2}
    2: {id: 3, value: 3}
    3: {id: 4, value: 4}
    4: {id: 5, value: 5}
]

接着咱們來看下第二段代碼:函數

const arr2 = [
    { id: 1, value: 1 },
    { id: 2, value: 2 },
    { id: 3, value: 3 },
    { id: 4, value: 4 },
    { id: 5, value: 5 },
]
arr2.forEach((item, index) => {
    if (item.id === 1) {
        item = { id: 6, value: 6 }
    }
})

將第二段代碼放入瀏覽器控制檯執行完以後,打印數組arr2:翻譯

[
    0: {id: 1, value: 1}
    1: {id: 2, value: 2}
    2: {id: 3, value: 3}
    3: {id: 4, value: 4}
    4: {id: 5, value: 5}
]

咱們能夠發現arr2中 [id = 1] 的元素並無被替換成咱們指望code

{ id: 6, value: 6 }

固然,最後我會說怎麼在forEach遍歷過程當中去替換原數組中的元素,如今咱們先來討論下,爲何會出現 [id = 1] 的元素爲何沒有被替換掉:對象

要想探究緣由,咱們就得將上述數組用照妖鏡照一照,看看它的真面目到底是如何內存

js中的數組類型,分爲兩大類,
一類是值類型 數值、布爾值、null、undefined
一類是引用類型 對象、數組、函數虛擬機

看下面代碼,簡單說明js字面量建立對象的過程 :it

let obj = { id: 1, name: 2 }
# 虛擬機在執行到 { id: 1, name: 2 } 就會在內存中建立一個對象
# 這個對象在內存中的地址假如爲 0x1110,再將此地址賦值給變量obj
# 此時obj的值實際爲0x1110

理解了上述js建立過程,那麼咱們來揭開arr2數組的真實面紗io

# 內存地址是16進制數表示,如下地址僅爲說明問題
const arr2 = [
    0x1110, 0x1111, 0x1112, 0x1113, 0x1114
]

看到arr2的真實面目,相信各位小夥伴應該明白了,上面展現的第二段代碼爲何無效

# 那麼咱們就來看看爲何下面item沒有被替換
arr2.forEach((item, index) => {
    # 咱們在遍歷的過程當中,咱們拿到的item值實際上是
    # 0x1110, 0x1111, 0x1112, 0x1113, 0x1114 5個地址
    if (item.id === 1) {
        # { id: 6, value: 6 } 是對象的字面量建立方式,會在內存中
        # 建立一個對象,並返回對象地址 假如爲 0x1115
        item = { id: 6, value: 6 }
        # 咱們再將 item = { id: 6, value: 6 } 語句翻譯一下
        # 0x1110 = 0x1115
        # 看到問題了嗎?將一個16進制數賦值給另一個16進制數
        # 其實這段是無效的賦值,也就被瀏覽器給忽略了,因此咱們在
        # 打印出得結果中發現 元素{id: 1, value: 1}並無被
        # 替換成{id: 6, value: 6}
    }
})

可能有些初學小夥伴有疑問,既然咱們在遍歷的過程當中拿到的是一個內存地址,那麼在最開始第一段代碼中,爲何又能將元素{ id: 1, value: 1 }的value值改變爲10呢,那麼請給我留言,不在這裏展開這個問題。

最後總結,forEach和map遍歷中 若是想改原數組,經過下面方式就好了

arr.forEach((item, index) => {
    if (condition) {
        arr[index] = something;
    }
})

之因此會聊到這個問題,也是團隊小夥伴談到forEach遍歷過程當中不能修改原數組,可是殊不知道爲何不能修改,以及真的要修改,又如何去修改。後面想了下,可能也有其餘的小夥伴有時也不太清楚,索性寫了篇小記,幫助理解。

相關文章
相關標籤/搜索