便利なJavaScriptワンライナー

開発でよく遭遇するするユースケースに対するワンライナーをまとめてみました。
適切に使用することで短くて読みやすいコードを書いていきましょうー

## EcmaScript
### 配列をシャッフル
``` JavaScript
const shuffleArray = (arr) => arr.sort(() => Math.random() - 0.5)
shuffleArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
// [8, 6, 5, 7, 9, 1, 2, 3, 10, 4]
```
@culageさんから偏りがある並び替えになるとご指摘をいただきました。
[@culageさんのコメント](https://qiita.com/tetsuyaohira/items/ac8e1fd3c249eb889753#comment-a0cff5179f671078af79)
(2022-10-30 追記)

### ユニークな配列を取得
``` JavaScript
const removeDuplicateArray = (arr) => [...new Set(arr)]
removeDuplicateArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

### 数値の配列の平均を取得する
``` JavaScript
const average = arr => arr.reduce((a, b) => a + b) / arr.length
average([43, 94, 13, 35, 73])
// 51.6
```

### 変数が配列かどうか
``` JavaScript
const fruit = '🍎'
const fruits = ["🍎", "🍌", "🥭", "🍊", "🍇"]
const isArray = (arr) => Array.isArray(arr)

isArray(fruit) // false
isArray(fruits) // true
```


### 先頭の一文字を大文字にする
``` JavaScript
// 
// const capitalize = str => str.split(' ').map(word => word[0].toUpperCase() + word.slice(1)).join(' ')
const capitalize = str => str.replace(/(^\w{1})|(\s+\w{1})/g, match => match.toUpperCase())
capitalize("javascript programing language")
//Javascript Programing Language
```


### 文字列を逆にする
``` JavaScript
const stringReverse = str => str.split('').reverse().join('')
stringReverse("回文とは")
// はと文回
stringReverse("たけやぶやけた")
//たけやぶやけた
```

### 小数点以下の数字を特定の桁数に丸める
JavaScriptで浮動小数点の少数を丸めるのは、少々扱いにくいです。
toFiexed()を使うと、指定した桁数で丸められますが、浮動小数点演算の仕組みが原因で、場合によっては誤差が発生します。
``` JavaScript
// ✅
Number((1.059).toFixed(2)) //1.06 OK
Number((1.047).toFixed(2)) //1.05 OK

// ❌
console.log(Number((1.005).toFixed(2))) // 1    NG. expected 1.01
console.log(Number((1.055).toFixed(2))) // 1.05 NG. expected 1.06
```

この動作を回避するために、数値を指数表記で表し、`Math.round()`を使用することで
指定の桁数に丸められた小数を取得できます。
``` JavaScript
const round = (n, d) => Number(Math.round(n + 'e' + d) + 'e-' + d)
round(1.005, 2) //1.01 OK
round(1.055, 2) //1.06 OK
```
@fujitanozomuさんから指数表現で渡すと想定外の結果が返ってきてしまうとご指摘をいただきました。
[@fujitanozomuさんのコメント](https://qiita.com/tetsuyaohira/items/ac8e1fd3c249eb889753#comment-185d0e90ca1cc0d98b98)
(2022-10-30 追記)

### ランダム文字列生成
``` JavaScript
const randomString = () => Math.random().toString(36).slice(2)
randomString(); //pjxl9h0x3k
```
@uasiさんから`Math.random()`がきりのいい値を返すと文字列が短くなってしまうとご指摘をいただきました。
[@uasiさんのコメント](https://qiita.com/tetsuyaohira/items/ac8e1fd3c249eb889753#comment-ca708843e78227f06b42)
(2022-10-30 追記)

### ランダムな 16 進数の色を生成する
``` JavaScript
const hexColor = () => '#' + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, '0')
hexColor() // #942d7e
```
@fujitanozomuさんから`#ffffff`が生成されないとご指摘をいただきました。
[@fujitanozomuさんコメント](https://qiita.com/tetsuyaohira/items/ac8e1fd3c249eb889753#comment-4e338092653672425a53)
(2022-10-30 追記)

### メールアドレスからドメイン名を抽出
``` JavaScript
const getDomain = (email) => email.substring(email.indexOf('@') + 1)
getDomain('google@gmail.com') // gmail.com
```


### 日付形式を逆にする
``` JavaScript
const transDate = (date) => date.split("-").reverse().join('-')
transDate('2022-10-23') // 23-10-2022
```

### 日の間隔を取得
``` JavaScript
const dayDif = (date1, date2) => Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000)
dayDif(new Date('2022-10-01'), new Date('2022-10-23')) //22
```

## Windowオブジェクト

### クリップボードにコピー
``` JavaScript
const copyToClipboard = (text) => navigator.clipboard?.writeText && navigator.clipboard.writeText(text)
copyToClipboard("Hello World!")
```

### ダークモードの検出
``` JavaScript
const isDarkMode = () => window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
console.log(isDarkMode()); // true or false
```

### トップにスクロール
``` JavaScript
const scrollToTop = (element) =>
  element.scrollIntoView({ behavior: 'smooth', block: 'start' })
const target = document.getElementById('topElement')
scrollToTop(target) // topElementまでスクロール
```

### 下にスクロール
``` JavaScript
const scrollToBottom = (element) =>
  element.scrollIntoView({ behavior: 'smooth', block: 'end' })
const target = document.getElementById('bottomElement')
scrollToBottom(target) // bottomElementまでスクロール
```

### ユーザーがページの一番下までスクロールしたかどうかを確認する
``` JavaScript
const scrolledToBottom = () => 
    document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight
scrolledToBottom() // true or false
```


### 要素の表示を切り替え
``` JavaScript
const toggle = element => element.style.display = (element.style.display === 'none' ? 'block' : 'none')
const target = document.getElementById('targetElement')
toggle(target) // hide
toggle(target) // show
```
@uasiさんから`display:block`でない要素に対して使うとまずいとご指摘をいただきました。
[@uasiさんコメント](https://qiita.com/tetsuyaohira/items/ac8e1fd3c249eb889753#comment-c17e2059daeba691523a)
(2022-10-30 追記)

### 要素がフォーカスされているかどうかを確認
``` JavaScript
const isFocus = (element) => element == document.activeElemnt
const target = document.getElementById('targetElement')
isFocus(target) // true or false
```


### 全てのCookieを消去
``` JavaScript
const clearCookies = () => 
    document.cookie.split(';').forEach(cookie => document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date(0).toUTCString()};path=/`))
clearCookies()
```

### テキストから HTML を取り除く
``` JavaScript
const stripHtml = html => (new DOMParser().parseFromString(html, 'text/html')).body.textContent || ''
stripHtml('<p><em>hello</em> <strong>world</strong></p>') // 'hello world'
```
@uasiさんから不可解な挙動があるとご指摘をいただきました。
[@uasiさんコメント](https://qiita.com/tetsuyaohira/items/ac8e1fd3c249eb889753#comment-c17e2059daeba691523a)
(2022-10-30 追記)