2019/3 JavaScriptの進化

今回は年々進化しているES2015以降のJavaScriptについてご紹介します。

JavaScriptとは

JavaScriptは、Netscapeが独自で始めたプログラミング言語で、各ブラウザベンダで動くようにECMAScriptという名前で標準化されました。しかし、慣習的に世の中ではECMAScriptと呼ばずJavaScriptと呼ぶことが一般的です。

このECMAScriptは、標準化団体によりプログラミング言語として1999年にバージョン3、2009年にバージョン5とアップデートしていました。 しかし、バージョンアップするのに非常に年月がかかったため、2015年以降はその年の間に新仕様で固まったものだけをアップデートする、毎年アップデート方式に変わりました。

そのため、2015年以降のJavaScriptバージョンは、ES2015(ECMAScript 2015)、ES2016という感じの略称で呼ぶようになってきました。

そしてES2015以降、知らない間に構文追加されているので、新しい記法で書かれたコードも読めるように以下でご紹介します。

ES2019

この年のアップデートは、あまり使い所がないかもしれません。

trimStart(), trimEnd()

// 空白文字の除去
'   abc'.trimStart(); // => 'abc'
'abc   '.trimEnd();   // => 'abc'

try catch引数省略可能に

try {
  throw new Error('exception!');
} catch {   // (error)を記述しなくてもいい
  console.log('エラー');
}

ES2018

スプレッド構文は大変便利で、ReactのReduxでよく使いました。

Promise.finally

// ajax通信時のエラーハンドリングに便利
new Promise((resolve, reject) => {
  setTimeout(resolve, 1000);
}).then(() => {
  console.log('成功時');
}).catch(e => {
  console.log('エラー時');
}).finally(() => {
  console.log('成功してもエラーでも実行される');
});

オブジェクトでもスプレッド構文

// オブジェクトを複製したり、別データを作るのに便利
const data = {
  width: 100,
  height: 200,
};
const house = {
  ...data,
  price: 4000,
};
console.log(house); // => { width: 100, height: 200, price: 4000 }

ES2017

padStartは地味に便利です。

String.prototype.padStart

// 日付処理に便利
'5'.padStart(2);       // => ' 5'
'5'.padStart(2, '0');  // => '05'

Object.values, Object.entries

// for文でオブジェクトデータを取り出すのに便利
const data = {
  japan : 'east',
  us : 'west',
}

for(const val of Object.values(data)){
  console.log(val);
}

for(const [key, val] of Object.entries(data)){
  console.log(key, val);
}

async / await

// 非同期処理を同期っぽく書ける構文
const timer = (time) => {
  return new Promise((resolve) => {
    setTimeout(resolve, msec)}
  );
};

(async () => {
  await sleep(1000);
  console.log('1秒立ちました.')
})();

ES2016

includesは直感的で便利です。indexOfの利用頻度は下がるでしょう。

Array.prototype.includes

// 配列内にデータがあるか存在確認
const pets = ['cat', 'dog', 'bat'];

pets.includes('cat');   // => true
pets.includes('mouse');   // => false

ES2015(ES6)

ES2015は名称の過渡期で、始めはES6(ECMAScript6)とも呼ばれていました。そのため過去の情報ではES6として説明されているサイトもよくあります。

let

// ブラケット内スコープで使えて再代入可能な変数let
if(a == 'a'){
  let x = 1;
  x = 2;
  console.log(x);  // 2が出力される
}
console.log(x);  // スコープ外なのでundefined

const

// ブラケット内スコープで使えて再代入できない変数const
if(a == 'a'){
  const x = 1;
  x = 2;  // 代入禁止エラーとなる
}
console.log(x);  // スコープ外なのでundefined

アロー関数

// 関数の書き方がスッキリするアロー関数
const add = (a, b)=>{
    return a + b;
};
add(1, 2);  // 3が戻ってくる

// こういう書き方もできる(読みにくいのでおすすめしない。)
const log = (msg) => console.log(msg); 
const alert = msg => alert(msg); 

テンプレートリテラル

// バッククォートで囲むことで変数を代入したり、複数行に渡って文字列定義をすることができます。
const error = '404 not found';
const msg = `
  以下のエラーが発生しました。
  ${error}
  しばらくしてから再度アクセスしてください。
`;
alert(msg);

スプレッド構文

// ...と書くこで、配列が展開された状態で使うことができる。
const array = [1, 2, 3];
const x = [...array, 4, 5, 6];   // [1, 2, 3, 4, 5, 6]
const y = [-2, -1, 0, ...array]; // [-2, -1, 0, 1, 2, 3]

Promise

// 非同期処理をすっきり記述できる構文
const timer = new Promise((resolve, reject)=>{
  setTimeout(()=>{
    resolve('finished.');
  }, 1000);
});

timer.then((msg)=>{
  console.log(msg) // => 1秒後に'finished.'
});

分割代入

// オブジェクトから必要な変数だけ抽出することができる
const data = {
  width: 100,
  height: 200,
  kind: 'dog',
  color: 'black',
};
const {width, height} = data;

importとexportによるモジュール構文

// Sample.js
// エクスポート定義する方法
export default (msg)=>{
  console.log(`デフォルトメッセージ:${msg}`);
};

export const name1 = (msg)=>{
  console.log(`name1メッセージ:${msg}`);
};

export const name2 = (msg)=>{
  console.log(`name2メッセージ:${msg}`);
};

// インポートする方法
import Sample, { name1, name2 } from './Sample';

Sample('sample');  // => デフォルトメッセージ:sample
name1('111');      // => name1メッセージ:111
name2('222');      // => name2メッセージ:222

trim

// 文字の両端の空白を取り除く
'  abc   '.trim();  // => 'abc'

以上になります。 ES2015が1番多くの構文が追加されましたが、細かいけど便利な記法が他のバージョンでも追加されたことがわかると思います。

Webpack & Babelを使うことが一般的となってきたので、ブラウザバーションを気にせず最新の記法を使える時代となったので、覚えておくといいですね。