JavaScriptの書き方をアップデート

# なぜこの記事を書いたか

2018年からAngularを用いたSPAを開発するプロジェクトに参画しているが、
そこで他の開発者が書いた**JavaScript(TypeScript)**が自分の知らない記法で書かれていたので
自分のJavaScriptイメージをアップデート(最新の仕様を理解)する必要があると感じたからである。

## Default parameters

関数に値が渡されない場合や`undefined`が渡された場合にデフォルトの値で初期化される。

```javascript
function add(num1, num2 = 1){
    console.log(num1 + num2);
}

add(3,2); // 5

add(3);   // 4
```

## Rest parameters

不特定多数の引数を配列として受け取る

```javascript
function showArray(...args){
    console.log(args);
}

function double(...args){
	
    // 配列のため、mapメソッドが使える
    const result = args.map(x => x*2);
    console.log(result);
}

showArray(3,2); // [3,2]

double(3,2);    // [6,4]
```

## Spread syntax

- 関数呼び出しでは0個以上の引数として扱われる
- Arrayリテラルでは0個以上の要素として扱われる
- Objectリテラルでは0個以上のkey-valueのペアとして扱われる

```javascript
function add(a, b, c){
    console.log(a + b + c);
}

const numbers = [3,2,1];

// 関数呼び出し
add(...numbers); // 6

// Arrayリテラル
console.log([6,5,4,...numbers]); // [6,5,4,3,2,1]

// Objectリテラル
console.log({...numbers}); // {"0": 3, "1": 2, "2": 1}
```

## for...of statement

iterableオブジェクトに対して反復的な処理をするループを作成する

```javascript
function add(args){

    let result = 0;

    for(let x of args){
        result+=x
    }

    console.log(result);
}

const numbers = [3,2,1];

add(numbers); // 6
```

## Template literals

```javascript
let placeholder = "プレースホルダー";

let str = `テンプレートリテラルを使用すると
改
行
や
${placeholder}を埋め込むことができます`;

console.log(str);

// テンプレートリテラルを使用すると
// 改
// 行
// や
// プレースホルダーを埋め込むことができます
```

## const

再代入や再宣言が不可(定数)

```javascript
const number = 100;
number = 200;　// TypeError: Assignment to constant variable.
```

## let

ブロックスコープの局所変数を宣言できる。任意で値を代入することができる。

```javascript
let num = 10;

if(10 === num){
    let num = 20;

    console.log("if scope:" + num); // if scope:20

}

// if文内で宣言されているnumとはスコープが異なるため代入されない
console.log(num); // 10
```

## Arrow functions

無名関数を`=>`で記述できる。

```javascript
// 従来の無名関数
const function1 = function(x){
    return x * 2;
}

// アロー関数を用いた書き方
const function2 = x => x * 2;

console.log(function1(3)); // 6
console.log(function2(5)); // 10
```

## Map

Mapはkey-valueで保持するオブジェクト。
keyとしてオブジェクトやプリミティブ値を使用することができる。

```javascript
let myMap = new Map();

let keyStr = '文字';
let keyObj = {};
let keyFunc = () => {};

myMap.set(keyStr, '値(str)');
myMap.set(keyObj, '値(object)');
myMap.set(keyFunc, '値(function)');

console.log(myMap.get(keyStr));  // 値(str)
console.log(myMap.get(keyObj));  // 値(object)
console.log(myMap.get(keyFunc)); // 値(function)
```

## Set

どんな型でも一意の値を格納する。値を重複して保持することができない。

```javascript
let mySet = new Set();
const myObj = {"1":100};

mySet.add(1);
console.log(mySet); // {1}
mySet.add(5);
console.log(mySet); // {1, 5}
mySet.add(1);
console.log(mySet); // {1, 5}
mySet.add(myObj);
console.log(mySet); // {1, 5, {"1":100}}
mySet.add(myObj);
console.log(mySet); // {1, 5, {"1":100}}
```

## Array.prototype.includes

特定の要素が配列に含まれているかどうかをbooleanで返却してくれる。

- 含まれている場合はtrue
- 含まれていない場合はfalse

```javascript
const array = ["北海道", "青森", "秋田"];

console.log(array.includes("北海道")); // true
console.log(array.includes("東京")); // false
```

## Exponentiation operator

べき乗の計算

```javascript
console.log(2 ** 10); // 1024
```

## Object.entries

引数で渡されたobjectを[key,value]の形で返却する

```javascript
const object1 = { foo: 'bar', baz: 42 };
console.log(Object.entries(object1));
// [ ['foo', 'bar'], ['baz', 42] ]
```

## Object.values

引数で渡されたobjectのプロパティの値を配列で返却する

```javascript
const object1 = { foo: 'bar', baz: 42 };
console.log(Object.values(object1));
// ['bar', 42]
```

## String padding

指定した長さの文字列になるように指定した文字列で埋めてくれる

```javascript
const str = '100';
console.log(str.padStart(5, '0'));
// 00100
```

## Object.getOwnPropertyDescriptors

指定したオブジェクトのすべてのプロパティディスクリプターを返却する

```javascript
const obj = {
    hoge: "hogehoge"
};

const descriptor = Object.getOwnPropertyDescriptors(obj);
console.log(descriptor.hoge.value); // "hogehoge"
```

## Trailing commas in function parameter lists and calls

関数の引数に末尾のカンマを使用できる

```javascript
function hoge (a, b,){}
```

## Async functions

非同期の処理を同期的に書くことができる

```javascript
function hoge(){
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('resolved');
        }, 2000);
    });
}

async function asyncCall() {
  console.log('calling');
  var result = await hoge();
  console.log(result);
  console.log('done')
  // calling
  // resolved
  // done の順で出力
}

asyncCall();
```