for循環和for in在遍歷數組中的區別

困惑

在練習數組操做的時候,但願實現刪除數組中特定元素(好比刪除字符「1」)的功能
很容易地就想到了利用for循環和splice方法數組

for (let i = 0; i < hobbies.length; i++) {
        if (hobbies[i] == "1") {
            hobbies.splice(i, 1);
            i--;
        }
    }

測試結果
"1", "2", "3","1", "1", "4", "1"
"2", "3", "4"

如願達成目標,不過想起來還有for in這個東西,彷佛寫起來更簡潔
那用for in行不行呢函數

for(var i in hobbies)
    {
        if(hobbies[i]=="1")
        {
            hobbies.splice(i,1);
            i--;
        }
    }
    
測試結果
"1", "2", "3", "1", "1","4"
"2", "3", "1", "4"

爲何中間多了一個"1"出來?發生了什麼?測試

測試

添加console.log語句觀測i值的變化code

for(var i in hobbies)
    {
        console.log("判斷前"+i);
        if(hobbies[i]=="1")
        {
            hobbies.splice(i,1);
            i=i+1;
        }
        console.log("判斷後"+i)
    }
結果
判斷前0
判斷後-1
判斷前1
判斷後1
判斷前2
判斷後1
判斷前3
判斷後3

能夠看到,在第一次刪去1後,i--由0變成了-1
但下一次判斷的時候,i直接由-1跳到了1對象

隱藏的陷阱

在查詢資料以後,才發現問題出在了i的類型上索引

標準的for循環中的i是number類型,表示的是數組的下標
可是for in循環中的i, 表示的是數組的key是string類型!原型鏈

因爲隱式類型轉換的機制,這個區別被隱藏了起來
由於我測試的時候,用的是i--
而字符串,在運用遞增遞減符號的時候,會把它轉換成number類型
所以雖然i是字符」1「,但也變成了0
若是我用的是i=i+1
字符串加數字,會把數字轉化成字符串拼接,出現01這樣的結果
那麼這個區別就會被我監測到
另外,在splice函數中,參數用了字符串也並無影響最後的結果,由於也進行了隱式轉換字符串

實際發生的事

在先前,咱們刪除了元素後,給i--,想固然地以爲下一次變量的值會+1,變回i,就能夠對刪除的元素後面的一個元素進行判斷(由於它的角標數值由i+1,變成了i)
在for循環中是沒事的,但在for in裏面
i--這個操做其實沒有任何意義,即使給i隨便賦一個值,它的下一次取值依然是i+1
由於它是根據數組的元素鍵值(索引)來進行遍歷的,string類型的0,1,2,3,4...arr.length-1已經排好了,並不會由於中途i的值有所變化而改變原型

除此以外,for in還有一些坑回調函數

•做用於數組的for-in循環體除了遍歷數組元素外,還會遍歷自定義屬性。舉個例子,若是你的數組中有一個可枚舉屬性myArray.name,循環將額外執行一次,遍歷到名爲「name」的索引。就連數組原型鏈上的屬性都能被訪問到。
•某些狀況下,for in可能按照隨機順序遍歷數組元素。

所以不適合用for in來遍歷數組
for in適合用來遍歷對象

P.S

若是用forEach呢
結果以下

hobbies.forEach(function(value,index,hobbies){
        console.log("判斷前"+index);
        if(value=="1")
        {
            hobbies.splice(index,1);
            console.log(typeof index);
            index=index-1;
            // console.log("二"+i);
        }
        console.log("判斷後"+index);
    });
["1", "2", "3", "1", "1", "4", "1"]
判斷前0
number
判斷後-1
判斷前1
判斷後1
判斷前2
number
判斷後1
判斷前3
判斷後3
判斷前4
number
判斷後3
["2", "3", "1", "4"]

數組中有幾項,那麼傳遞進去的匿名回調函數就執行幾回

相關文章
相關標籤/搜索