每天推薦一個 GitHub 優質開源項目和一篇精選英文科技或編程文章原文,歡迎關注開源日報。交流QQ群:202790710;微博:https://weibo.com/openingsource;電報群 https://t.me/OpeningSourceOrg


今日推薦開源項目:《娛樂向的語言 Rockstar》傳送門:GitHub鏈接

推薦理由:這是個非常娛樂向的語言……因為它的語句基本都是由很容易理解的真正的英文詞語組成的。舉個例子就知道了,在 c 語言中,你肯定經常寫這樣的句子

x=123

但是在 Rockstar 中,你應該這麼寫

Put 123 into x

除此之外還有各種有意思的語法,當作娛樂去看一看也不錯


今日推薦英文原文:《Here』s how you can make better use of JavaScript arrays》作者:pacdiv

原文鏈接:https://medium.freecodecamp.org/heres-how-you-can-make-better-use-of-javascript-arrays-3efd6395af3c

推薦理由:顧名思義,這篇文章講的是如何更好的使用 JS 中的數組。

Here』s how you can make better use of JavaScript arrays

Quick read, I promise. Over the last few months, I noticed that the exact same four mistakes kept coming back through the pull requests I checked. I』m also posting this article because I』ve made all these mistakes myself! Let』s browse them to make sure we correctly use Array methods!

Replacing Array.indexOf with Array.includes

「If you』re looking for something in your Array, use Array.indexOf.」 I remember reading a sentence like this one in my course when I was learning JavaScript. The sentence is quite true, no doubt!

Array.indexOf 「returns the first index at which a given element can be found,」 says the MDN documentation. So, we use the returned index later in our code, and Array.indexOf is the solution.

But, what if we only need to know if our array contains a value or not? Seems like a yes/no question, a boolean question I would say. For this case, I recommend using Array.includes which returns a boolean.

'use strict';

const characters = [
  'ironman',
  'black_widow',
  'hulk',
  'captain_america',
  'hulk',
  'thor',
];

console.log(characters.indexOf('hulk'));
// 2
console.log(characters.indexOf('batman'));
// -1

console.log(characters.includes('hulk'));
// true
console.log(characters.includes('batman'));
// false

Using Array.find instead of Array.filter

Array.filter is a very helpful method. It creates a new array from another one with all items passing the callback argument. As indicated by its name, we must use this method for filtering, and for getting a shorter array.

But, if we know our callback function can return only one item, I would not recommend it — for example, when using a callback argument filtering through a unique ID. In this case, Array.filter would return a new array containing only one item. By looking for a specific ID, our intention may be to use the only value contained in the array, making this array useless.

Let』s talk about the performance. To return all items matching the callback function, Array.filter must browse the entire array. Furthermore, let』s imagine that we have hundreds of items satisfying our callback argument. Our filtered array would be pretty big.

To avoid these situations, I recommend Array.find. It requires a callback argument like Array.filter, and it returns the value of the first element satisfying this callback. Furthermore, Array.find stops as soon as an item satisfies the callback. There is no need to browse the entire array.

'use strict';

const characters = [
  { id: 1, name: 'ironman' },
  { id: 2, name: 'black_widow' },
  { id: 3, name: 'captain_america' },
  { id: 4, name: 'captain_america' },
];

function getCharacter(name) {
  return character => character.name === name;
}

console.log(characters.filter(getCharacter('captain_america')));
// [
//   { id: 3, name: 'captain_america' },
//   { id: 4, name: 'captain_america' },
// ]

console.log(characters.find(getCharacter('captain_america')));
// { id: 3, name: 'captain_america' }

Replacing Array.find with Array.some

I admit I』ve made this mistake many times. Then, a kind friend told me to check the MDN documentation for a better way. Here』s the thing: this is very similar to our Array.indexOf/Array.includes case above.

In the previous case, we saw Array.find requires a callback as an argument and returns an element. Is Array.find the best solution if we need to know whether our array contains a value or not? Probably not, because it returns a value, not a boolean. With an array containing objects, Array.find would return an entire object while we may only need a boolean. This could cause performance issues.

For this case, I recommend using Array.some which returns the needed boolean.

'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

Using Array.reduce instead of chaining Array.filter and Array.map

Let』s face it, Array.reduce isn』t simple to understand. It』s true! But, if we run Array.filter, then Array.map it feels like we』re missing something, right?

I mean, we browse the array twice here. The first time to filter and create a shorter array, the second time a create a new array (again!) containing new values based on the ones we obtained from Array.filter. To get our new array, we used two Array methods. Each method has its own callback function and an array that we cannot use later — the one created by Array.filter.

To avoid low performances on this subject, my advice is to use Array.reduce instead. Same result, better code! Array.reduce allows you to filter and add the satisfying items into an accumulator. As an example, this accumulator can be a number to increment, an object to fill, a string or an array to concat.

In our case, since we』ve been using Array.map, I recommend using Array.reduce with an array to concat as an accumulator. In the following example, depending on the value for env, we will add it into our accumulator or leave this accumulator as is.

'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'] }
// ]

That』s it!

Hope this helps. Be sure to leave comments if you have any thoughts on this article or have any other use cases to show. And if you found it helpful, give me some claps ?. Thanks for reading!


每天推薦一個 GitHub 優質開源項目和一篇精選英文科技或編程文章原文,歡迎關注開源日報。交流QQ群:202790710;微博:https://weibo.com/openingsource;電報群 https://t.me/OpeningSourceOrg