JS數組降維--Array.prototype.concat.apply([], arr)

多維數組(尤其是二維數組轉化爲一維數組是業務開發中的常用邏輯,最近跟着黃軼老師學習Vue2.6.1.1版本源碼時,看到源碼對二維數組降維的代碼,所以這裏來寫一篇,記錄一下,加強印象

Vue源碼學習

二維數組降爲一維數組

循環降維

let children = [1, 2, 3, [4, 5, 6], 7, 8, [9, 10]];
function simpleNormalizeChildren(children) {
  let reduce = [];
  for (let i = 0; i < children.length; i++) {
    if (Array.isArray(children[i])) {
      for (let j = 0; j < children[i].length; j++) {
        reduce.push(children[i][j]);
      }
    } else {
      reduce.push(children[i]);
    }
  }
  return reduce;
}
simpleNormalizeChildren(children) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

此方法思路簡單,利用雙重循環遍歷二維數組中的每個元素並放到新數組中。

concat降維

MDN上對於concat的介紹
“concat creates a new array consisting of the elements in the object on which it is called, followed in order by, for each argument, the elements of that argument (if the argument is an array) or the argument itself (if the argument is not an array).”
concat
如果concat方法參數是一個元素,該元素會被直接插入到新數組中;如果參數是一個數組該數組的各個元素將被插入到新數組中;將該特性應用到代碼中:

let children = [1, 2, 3, [4, 5, 6], 7, 8, [9, 10]];
function simpleNormalizeChildren(children) {
  let reduce = [];
  for (let i = 0; i < children.length; i++) {
    reduce = reduce.concat(children[i]);
  }
  return reduce;
}
simpleNormalizeChildren(children) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

children 的元素如果是一個數組,作爲concat方法的參數數組中的每一個子元素會被獨立插入進新數組。利用concat方法,我們將雙重循環簡化爲了單重循環。

apply和concat降維

下MDN上對於apply方法的介紹
“The apply() method calls a function with a given this value and arguments provided as an array.”
apply
apply方法會調用一個函數,apply方法的第一個參數作爲被調用函數的this值,apply方法的第二個參數(一個數組,或類數組的對象)作爲被調用對象的arguments值,也就是說該數組的各個元素將會依次成爲被調用函數的各個參數;將該特性應用到代碼中:

let children = [1, 2, 3, [4, 5, 6], 7, 8, [9, 10]];
function simpleNormalizeChildren(children) {
  return Array.prototype.concat.apply([], children);
}
simpleNormalizeChildren(children) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

children作爲apply方法的第二個參數,本身是一個數組,數組中的每一個元素(還是數組,即二維數組的第二維)會被作爲參數依次傳入到concat中,效果等同於[].concat(1, 2, 3, [4, 5, 6], 7, 8, [9, 10])。利用apply方法,我們將單重循環優化爲了一行代碼

Vue2.6.11版本源碼降維

let children = [1, 2, 3, [4, 5, 6], 7, 8, [9, 10]];
// :any 可以去掉 這裏是Vue通過Flow指定傳入的參數類型可以是任意類型
function simpleNormalizeChildren(children: any) {
  for (let i = 0; i < children.length; i++) {
    if (Array.isArray(children[i])) {
      return Array.prototype.concat.apply([], children);
    }
  }
  return children;
}

simpleNormalizeChildren(children); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

多維數組降爲一維數組

遞歸降維

遞歸函數就是在函數體內調用自己

遞歸函數的使用要注意函數終止條件避免死循環

// 多維數組
let children = [1, [2,3], [4, [5, 6, [7, 8]]], [9, 10]];
function simpleNormalizeChildren(children) {
  for (let i = 0; i < children.length; i++) {
    if (Array.isArray(children[i])) {
      children = Array.prototype.concat.apply([], children);
      for(let j =0; j<children.length; j++) {
        simpleNormalizeChildren(children)
      }
    }
  }
  return children;
}
simpleNormalizeChildren(children); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

大家有更好的降維方法嘛;歡迎留言討論


謝謝你閱讀到了最後
期待你,點贊、評論、交流

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章