JavaScript省略形多すぎ問題

JavaScript(ES6以降)、省略形が多くてわけがわからない。

# アロー関数

[アロー関数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)

```js:基本形
const printMessage = (msg) => {
  console.log(msg)
}
printMessage('hogehoge')


const sum = (x, y) => {
  return x + y
}
sum(1, 2) // 3
```

## 引数が一つなら`()`省略可

```js
const printMessage = msg => {
  console.log(msg)
}

// 引数が２つ以上の場合は省略不可
const sum = x, y => { // シンタックスエラー！
  return x + y
}
// デフォルト引数を使う場合は省略不可
const hoge = msg = 'hogehoge' => { // シンタックスエラー！
  console.log(msg)
}
// スプレッド演算子を使う場合は省略不可
const hoge = ...args => { // シンタックスエラー！
  console.log(args)
}
// 引数がない場合は省略不可
const fuga = () => {
  console.log('hoge')
}
```

## 式の場合は`{}`省略可

```js
// console.log(msg)はundefinedを返す式(expression)なので省略可
const printMessage = msg => console.log(msg)
printMessage('hogehoge')

// 「return x + y」は式(expression)ではなく、文(statement)なので省略不可
const sum = (x, y) => return x + y // シンタックスエラー！
```

## 式の場合は`return`省略可

```js
// 「x + y」は式なので{}省略可でreturn省略可
const sum = (x, y) => x + y
sum(1, 2) // 3
```

```js
[1, 2, 3].every((x) => { // true
  return x > 0
})
// ２つは同じ
[1, 2, 3].every(x => x > 0) // true
```

こんなこともできる(実用的かどうかは別として)

```js
const hoge = (x) => {
  return (y, z) => {
    return x * y * z
  }
}
hoge(2)(3, 4) // 24

const hoge = x => (y, z) => x * y * z
hoge(2)(3, 4) // 24
```

よ、読めねえ！

# プロパティ名省略代入

正式名称不明。
引数の変数名がそのままオブジェクトのプロパティ名になる。
JSONデータ作るときとかに重宝してる。

```js:基本形
const i = 1
const str = 'hogehoge'
const arr = [1, 2, 3]
const obj = {
  i: i,
  str: str,
  arr: arr,
}

console.log(obj) // { i: 1, str: 'hogehoge', arr: [ 1, 2, 3 ] }
```

```js:省略形
const i = 1
const str = 'hogehoge'
const arr = [1, 2, 3]

const obj = {i, str, arr}

console.log(obj) // { i: 1, str: 'hogehoge', arr: [ 1, 2, 3 ] }
```

# 分割代入

## オブジェクトの分割代入

```js:基本形
const obj = {
  hoge: 'hogehoge',
  fuga: 'fugafuga',
  piyo: 'piyopiyo',
}
const hoge = obj.hoge
const piyo = obj.piyo
console.log(hoge) // hogehoge
console.log(piyo) // piyopiyo
```


```js:省略形
const obj = {
  hoge: 'hogehoge',
  fuga: 'fugafuga',
  piyo: 'piyopiyo',
}
const {hoge, piyo} = obj
console.log(hoge) // hogehoge
console.log(piyo) // piyopiyo
```

## 配列の分割代入

こっちはあまり使わなさそうなのでMDN見てね
[分割代入 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)

```js

const hoge = [1, 2, 3]

const [one, two, three] = hoge
console.log(one) // 1
console.log(two) // 2
console.log(three) // 3
```

## モジュール使う時に便利に使えます

```js
/*
const util = require('util')
const fs = require('fs')
const pStat = util.promisify(fs.stat)
*/
const { promisify } = require('util')
const { stat } = require('fs')
const pStat = promisify(stat)
```

## 引数にも使えます

```js
const Oct1 = new Date(2018, 9, 1) // 2018-10-01
const myData = {now: Oct1, count: 1}

/*
const yesterday = (obj) => {
  const now = obj.now ? obj.now : new Date()
  return new Date(now.getFullYear(), now.getMonth(), now.getDate()-1)
}
*/
const yesterday = ({now = new Date()}) => new Date(now.getFullYear(), now.getMonth(), now.getDate()-1)
yesterday(myData) // 2018-09-30


/*
const countUp = (obj) => {
  let count = obj.count ? obj.count : 1
  return ++count
}
*/
const countUp = ({count = 1}) => ++count

countUp(myData) // 2
console.log(myData.count) // 1　

// 参照オブジェクトの操作ではなく、あくまで「代入」なので以下とは異なる
const countUp2 = (obj) => {
  return ++obj.count // ここでobj.countが+1される
}

countUp2(myData) // 2
console.log(myData.count) // 2
```

# スプレッド演算子

[スプレッド構文 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

スプレッド演算子`...`で配列やオブジェクトが展開できちゃう。

## 関数呼び出し

```js
const sum = (x, y, z) => x + y + z

const arr = [1, 2, 3]
sum(...arr) // 6
```

## Array リテラル

```js
const arr1 = [1, 2, 3]
const arr2 = [4, 5]
const merged_arr = [...arr1, ...arr2, 6, 7]
console.log(merged_arr) // [ 1, 2, 3, 4, 5, 6, 7 ]
```

## 可変長引数

```js
const sum = (...args) => args.reduce((x, y) => x + y)
sum(1, 2, 3, 4, 5) // 15
sum(2, 4, 6, 8) // 20
```

## Object リテラル

ES9からの新機能
今まで`Object.assign()`を使ってやっていたオブジェクトのクローンが簡単に書けちゃう

```js
const obj = { hoge: 1, fuga: 2 }
const objClone = { ...obj, piyo: 3 }
const objRef = obj

obj.hoge++
console.log(obj) // { hoge: 2, fuga: 2 }
console.log(objClone) // { hoge: 1, fuga: 2, piyo: 3 }
console.log(objRef) // { hoge: 2, fuga: 2 }
```