Array.prototype.hogehoge vs Lodash ~ 2018年でもLodashは速いのか? ~

なんか枠が空いているので、2回目の投稿です。JavaScriptの話です。[1回目](https://qiita.com/KuwabataK/items/3478f0d322ae27191d6e)の投稿とはなんの関係もないです。

## 2016年はLodashのほうが速かった・・・らしい

みんな大好き[Lodash](https://lodash.com/)。皆さん使ってますか？
私は主にオブジェクトを`cloneDeep`するのに使ってます。乱用すると重くなるのがアレですが、でも標準でDeepCopyする機能ないんだもん、しょうがないよね。

しかしながらそんなLodashもES6から`map`や`forEach`、`filter`など、主に配列操作でよく使う関数たちが標準実装されるようになり、だんだん影が薄くなってきました。

でも、そんな状況でもあえて標準の`map`ではなくLodashの`map`こともあるようです。何故かと言うと実行速度が違うから。[例えば2016年に書かれたこの記事では](http://blog.aqutras.com/entry/2016/05/26/210000)標準の`map`に比べてLodashの`map`はだいたい5倍ぐらい速いと書かれています。なるほど、2016年はそうだったのか。

しかし、今はもう2018年も終わりを迎えようとしています。きっと標準の`map`関数も最適化が進んで速くなっているはず！

というわけでベンチマークを取ってみました。

今回は[MeasureThat.net](https://www.measurethat.net/)というサイトと使ってベンチマークを取ります。これはブラウザ上でBenchmarkJS (v.2.1.1) を動かすことができるWebアプリです。便利

## Map

https://www.measurethat.net/Benchmarks/Show/4353/0/arrayprototypemap-vs-lodash-map

実行コード

``` .js
const array = [...Array(100000).keys()];
array.map(n => n*2)   // Array.protptype.map
_.map(array,n => n*2) // lodash map
```

### chrome
<img width="905" alt="スクリーンショット 2018-12-10 01.34.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/1e4544cf-1132-d4e5-7903-4e8424ba8ba9.png">

### Firefox

<img width="905" alt="スクリーンショット 2018-12-10 01.35.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/fbae149e-9456-8d0f-7664-cff601e7d7c9.png">



### Safari
<img width="905" alt="スクリーンショット 2018-12-10 01.36.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/6b5b8a1c-767c-a8f2-d4ba-ed38fcee3f69.png">


Mapは全体的にLodashのほうが速そうですね。特にChrome環境下で差が顕著です


## forEach

https://www.measurethat.net/Benchmarks/Show/4354/0/arrayprototypeforeach-vs-lodash-foreach

``` .js
const array = [...Array(100000).keys()];
array.forEach(n => n*2)   // Array.protptype.forEach
_.forEach(array,n => n*2) // lodash forEach
```


### chrome
<img width="905" alt="スクリーンショット 2018-12-10 01.27.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/d2a308ac-dcd7-0498-c59d-1e11870bd061.png">



### Firefox

<img width="905" alt="スクリーンショット 2018-12-10 01.29.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/6d7e3918-37f2-2799-2a4e-fd785e012ac9.png">



### safari

<img width="905" alt="スクリーンショット 2018-12-10 01.33.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/de487b05-59e7-f3b5-f6c0-64419418ccce.png">

なんかforEachは標準の関数のほうが速そうです。なんで違うねん。特にFirefoxで差が大きいです

## filter

https://www.measurethat.net/Benchmarks/Show/4386/0/arrayprototypefilter-vs-lodash-filter2

実行コード

``` .js
const array = [...Array(100000).keys()];
const ram = Math.floor(100000 * Math.random());
array.filter(n => n === ram)          // Array.prototype.filter
_.filter(array,n => n === ram)        // Lodash filter
```

### chrome

<img width="898" alt="スクリーンショット 2018-12-10 01.21.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/ac0a606b-7ff6-f993-7b5b-22cdeec112bf.png">



### Firefox

<img width="920" alt="スクリーンショット 2018-12-10 01.22.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/e6372d3e-1625-7bd1-30cd-36a6e4cc83f9.png">


### safari

<img width="897" alt="スクリーンショット 2018-12-10 01.26.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/8f278d32-9745-9618-35c4-58e8947d447d.png">


filterはどちらもあまり変わらないですね。ブラウザによって早かったり遅かったりです。

## find

https://www.measurethat.net/Benchmarks/Show/4387/0/arrayprototypefind-vs-lodash-find2

実行コード

``` .js
const array = [...Array(100000).keys()];
const ram = Math.floor(100000 * Math.random());
array.find(n => n === ram)          // Array.prototype.find
_.find(array,n => n === ram)        // Lodash find
```

### chrome
<img width="907" alt="スクリーンショット 2018-12-10 01.13.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/18846533-8b79-96ac-6a69-d6db57598ec0.png">





### Firefox

<img width="931" alt="スクリーンショット 2018-12-10 01.14.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/31e2f6a2-3274-63f6-991e-4200803a6e4f.png">

### safari

<img width="919" alt="スクリーンショット 2018-12-10 01.18.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/af9b24c7-dad9-c332-4e6d-6282c985baac.png">


findも傾向としてはfilterと似たような感じ。Firefox環境下では標準の関数のほうが速そうです。

## some

https://www.measurethat.net/Benchmarks/Show/4388/0/arrayprototypesome-vs-lodash-some2

実行コード

``` .js
const array = [...Array(100000).keys()];
const ram = Math.floor(100000 * Math.random());
array.some(n => n === ram)          // Array.prototype.some
_.some(array,n => n === ram)        // Lodash some
```

### chrome
<img width="890" alt="スクリーンショット 2018-12-10 01.08.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/09a57dd2-73c3-2e69-0223-f63853e85b78.png">

### Firefox

<img width="920" alt="スクリーンショット 2018-12-10 01.12.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/71875653-e19b-27f4-bed1-cb235aa9a738.png">


### safari

<img width="893" alt="スクリーンショット 2018-12-10 01.11.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/14a13b4a-5861-361d-da7e-d2717aef92d4.png">


~~違いがわからない~~

## every

https://www.measurethat.net/Benchmarks/Show/4389/0/arrayprototypeevery-vs-lodash-every2

実行コード

``` .js
const array = [...Array(100000).keys()];
const ram = Math.floor(100000 * Math.random());
array.every(n => n === ram)          // Array.prototype.every
_.every(array,n => n === ram)        // Lodash every
```

### chrome
<img width="937" alt="スクリーンショット 2018-12-10 01.03.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/c21d0035-9fbc-edc7-84e4-9861c32c56d3.png">


### Firefox

<img width="950" alt="スクリーンショット 2018-12-10 01.07.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/286298a4-ed57-09b3-2e44-c0968fbb2fa3.png">



### safari

<img width="947" alt="スクリーンショット 2018-12-10 01.06.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/93999/90ea621c-da96-5f3f-b15b-13b2e0dcc66b.png">


everyは標準の関数のほうが速そうです。

## まとめ

以上、私が普段よく使うものだけまとめましたが、map以外は標準のものを使っていれば良さそうですね。
ただ、今回は性能が問題になりそうなモバイルブラウザでは測定していないですし、babelでトランスコンパイルしていたりするとまた違った結果になりそうなので、あくまで参考です。

まあぶっちゃけ、frontでめちゃめちゃ重い計算処理をすることってあまりないですし、DOM描画のほうが実行コスト高くなりがちなので、実際のプロジェクトではあまり気にしなくても良いのかもしれません。