【譯】如何更好的使用javascript陣列

frontman發表於2018-09-04

趕緊閱讀讀此文,我保證,在過去的幾個月裡我,我確定我在陣列問題上犯過4次錯誤。於是我寫下這篇文章,閱讀這篇文章可以讓你更準確的使用javascript陣列的一些方法

使用Array.includes替代 Array.indexOf

“如果你在陣列中搜尋某個元素,那麼請使用Array.indexOf” ,我記得在學習javascript時看到過這個句子,毫無疑問,這句話很對。

MDN文件上這樣描述 rray.indexOf“返回第一個被搜尋到的元素的下標(索引)” ,所以如果你想要搜尋某個元素的下標,那麼Array.indexOf可以很好的解決。

但是,如果我們想檢視一個陣列中是否包涵某個元素該如何做呢。就像yes/no這樣的問題,也就是布林值。這裡我們推薦使用返回布林值的Array.includes方法。

const persons = ["jay","leinov","jj","nico"];

console.log(persons.indexOf("leinov"));
// 1

console.log(persons.indexOf("beyond"));
// -1


 console.log(persons.includes("leinov"));
// true

console.log(persons.includes("beyond"));
// false

使用Array.find代替Array.filter

Array.filter是一個非常有用的方法,它通過一個陣列的回撥引數建立一個新的陣列,正如他的名字所示,我們使用它過濾出一個更短的陣列

但是 如果我們明確的知道回撥函式返回的只是陣列中的一項,這樣的話我不推薦使用他,例如,當使用的回撥引數過濾的是一個唯一的id,這種情況,Array.filter返回一個新的包涵這一項的陣列。尋找一個特殊的id,我們目的只想取一項出來,這個返回的陣列就是無用的。

接下來我們看下效能,為了返回能夠匹配回撥函式的每一項,Array.filter必須檢索整個陣列,此外讓我們想象下,我們有數百個項滿足我們的回撥引數函式,我們過濾的陣列就非常大了。

為了避免這種情況,我推薦Array.find ,他同Array.filter一樣需要一個回撥函式引數,並且返回第一個能夠滿足回撥函式引數的那一項。並且Array.find 在滿足篩選後停止篩選,不會檢索整個陣列。

use strict`;

const singers = [
  { id: 1, name: `周杰倫` },
  { id: 2, name: `李建` },
  { id: 3, name: `庾澄慶` },
  { id: 4, name: `謝霆鋒` },
  { id: 5, name: `周杰倫` },
];

function getSinger(name) {
  return signer => signer.name === name;
}

console.log(singers.filter(getSinger(`周杰倫`)));
// [
//   { id: 1, name: `周杰倫` },
//   { id: 5, name: `周杰倫` },
// ]

console.log(characters.find(getSinger(`周杰倫`)));
// { id: 1, name: `周杰倫` }

使用Array.some代替Array.find

我承認經常在這上面犯錯,然後,我的一個好朋友提醒我看下MDN文件去尋找一個更好的方式解決,這點跟上面的Array.indexOf/Array.includes很相似

在前面提到 Array.find 需要一個回撥函式作為引數來返回一個滿足的元素。如果我們需要知道陣列是否包涵某個值時,Array.find是最好的方式嗎。或許不是,因為返回的是一個值,不是一個布林值。

在這種情況下,我推薦使用Array.some,它返回的是一個是否滿足回撥引數的布林值

`use strict`;

const characters = [
  { id: 1, name: `ironman`, env: `marvel` },
  { id: 2, name: `black_widow`, env: `marvel` },
  { id: 3, name: `wonder_woman`, env: `dc_comics` },
];

function hasCharacterFrom(env) {
  return character => character.env === env;
}

console.log(characters.find(hasCharacterFrom(`marvel`)));
// { id: 1, name: `ironman`, env: `marvel` }

console.log(characters.some(hasCharacterFrom(`marvel`)));
// true

使用Array.reduce 代替 Array.filter and Array.map

讓我們來看看Array.reduce,Array.reduce並不太好理解,但是如果我們執行Array.filter,Array.map感覺我們好像錯過了什麼。

我的意思是,我們檢索了陣列兩次,第一次過濾和建立了一個短的陣列,第二次建立了一個新的包涵我們過濾獲取到的陣列。為了獲取結果我們使用了兩個陣列方法,每個方法都有一個回撥函式和一個陣列,其中一個Array.filter建立的我們之後是用不到的。

為了避免這個效能的問題,我建議使用Array.reduce來代替。相同的結果,更好的程式碼。Aaray.reduce允你篩選和新增滿足的專案到累加器中。例如,這個累加器可以是一個數字增量,一個要填充的物件,一個字串或一個陣列。

在我們之前的例子中,我們一直在使用Array.map,所以我建議使用Array.reduce來使用累加器來連線陣列。在下面的示例中,根據env的值,我們將將其新增到累加器中,或者將此累加器保留為原來的值。

`use strict`;

const characters = [
  { name: `ironman`, env: `marvel` },
  { name: `black_widow`, env: `marvel` },
  { name: `wonder_woman`, env: `dc_comics` },
];

console.log(
  characters
    .filter(character => character.env === `marvel`)
    .map(character => Object.assign({}, character, { alsoSeenIn: [`Avengers`] }))
);
// [
//   { name: `ironman`, env: `marvel`, alsoSeenIn: [`Avengers`] },
//   { name: `black_widow`, env: `marvel`, alsoSeenIn: [`Avengers`] }
// ]

console.log(
  characters
    .reduce((acc, character) => {
      return character.env === `marvel`
        ? acc.concat(Object.assign({}, character, { alsoSeenIn: [`Avengers`] }))
        : acc;
    }, [])
)
// [
//   { name: `ironman`, env: `marvel`, alsoSeenIn: [`Avengers`] },
//   { name: `black_widow`, env: `marvel`, alsoSeenIn: [`Avengers`] }
// ]

原文:Here’s how you can make better use of JavaScript arrays
如有哪裡翻譯錯誤請指正 3Q


相關文章