Help us understand the problem. What is going on with this article?

最新のJavaScript: ES2016からES2019までの知るべき全て

訳者前書き

本記事は、InspiredWebDevの原文記事(英語)について、自身の理解を深める為に日本語翻訳したものです。

はじめに

JavaScriptは絶えず進化している言語であり、過去数年で多くの新機能がECMAScriptの仕様に追加されました。

この記事は、Alberto氏の著書「最新のJavaScriptの完全ガイド(Complete Guide to Modern JavaScript)」の抜粋です。
同書では、ES2016、ES2017、ES2018、ES2019の新規追加要素について説明しています。

記事の最後に、すべてを要約したチートシートをダウンロードするためのリンクがあります。

1. ES2016の新機能

ES2016で導入された2つの新機能について説明します。

2. Array.prototype.includes()

配列のincludes()メソッドは、自身の配列に特定の要素が含まれている場合はtrueを、そうでない場合はfalseを返します。

let array = [1,2,4,5];

array.includes(2);
// true
array.includes(3);
// false

includes() と 要素検索開始インデックス (fromIndex) の組み合わせ

.includes()に対して、要素の検索を開始するためのインデックスを提供できます。
デフォルト(インデックスを指定しない場合)の値は0です。また、負の値を渡すこともできます。
※訳者注:負の値を渡した場合、配列要素数+負の値をインデックスに指定した扱いとなります。

1番目の引数は検索する要素、2番目の引数は検索を開始するインデックスです。

let array = [1,3,5,7,9,11]; // 訳者注:配列のインデックスは0番目から始まります

array.includes(3,1);
// 配列の1番目から数字の3を探します
// true
array.includes(5,4);
// 配列の4番目から数字の5を探します
// false
array.includes(1,-1);
// 配列の(配列要素数-1)番目から数字の1を探します
// false
array.includes(11,-3);
// 配列の(配列要素数-3)番目から数字の11を探します
// true

array.includes(5,4);falseを返します。
配列は数字の5を含みますが、同要素より後ろの4番目の要素から探し始めた為です。

array.includes(1,-1);falseを返します。
配列は数字の1を含みますが、同要素より後ろの(配列要素数6 - 1 =) 5番目の要素から探し始めた為です。

array.includes(11,-3);trueを返します。
配列は数字の11を含んでおり、同要素より手前の(配列要素数6 - 3 =) 3番目の要素から探し始めた為です。

3. 指数演算子(べき乗)

ES2016より前の仕様では、指数計算を次のように記述していました。

Math.pow(2,2);
// 4
Math.pow(2,3);
// 8

ES2016で追加された新しい指数演算子を使うと、次のように記述できます。

2**2;
// 4
2**3;
// 8

指数演算子は、次の例のように複数の操作を組み合わせる場合に、非常に役立ちます。

2**2**2;
// 16
Math.pow(Math.pow(2,2),2);
// 16

上記のようなケースでMath.pow()を使用するには、同関数を継続的に連結する必要があり、非常に長く複雑になります。
指数演算子は、同じことをより簡潔に行う方法を提供します。

4. ES2017の新機能

ES2017では数多くの素晴らしい新機能が導入されました。
ここでは、それらの機能について説明します。

5. 文字列のパディング(.padStart() および .padEnd())

文字列の末尾(.padEnd())または先頭(.padStart())に余白を追加できます。

"hello".padStart(6);
// " hello"
"hello".padEnd(6);
// "hello "

余白が6つ分必要と指定したのに、両方のケースで1つの空白しか取得できなかったのは何故でしょうか?
それは、padStartpadEndが、元の文字列で埋めきれない空きスペースを埋める為です。
この例では、「hello」は5文字で、パディングは6文字ですので、空きスペースは1文字分しか残っていません。

こちらの例を見てください。

"hi".padStart(10);
// 10 - 2 = 8 empty spaces
// "        hi"
"welcome".padStart(10);
// 10 - 6 = 4 empty spaces
// "   welcome"

padStartを用いて右揃えする

padStartは何かを右揃えしたい場合に使用できます。

const strings = ["short", "medium length", "very long string"];

const longestString = strings.sort(str => str.length).map(str => str.length)[0];

strings.forEach(str => console.log(str.padStart(longestString)));

// very long string
//    medium length
//            short

上記の例では、予め用意した配列内から、最も長い文字列の要素を取得し、その文字列の長さを測定しました。
次に配列の各要素に対してpadStartを測定した文字長で適用することで、すべての文字列を綺麗に右揃えにできました。

カスタム値をパディングに追加する

パディングとして空白を追加するだけでなく、文字列と数字の両方を渡すことができます。

"hello".padEnd(13," Alberto");
// "hello Alberto"
"1".padStart(3,0);
// "001"
"99".padStart(3,0);
// "099"

6. Object.entries() および Object.values()

最初にオブジェクトを作成しましょう。

const family = {
  father: "Jonathan Kent",
  mother: "Martha Kent",
  son: "Clark Kent",
}

JavaScriptの以前のバージョンでは、次のようにオブジェクト内の値にアクセスしていました。

Object.keys(family);
// ["father", "mother", "son"]
family.father;
"Jonathan Kent"

Object.keys()は、値にアクセスする為に必要なキーのみの配列を返しました。

オブジェクトにアクセスする方法は更に2つあります。

Object.values(family);
// ["Jonathan Kent", "Martha Kent", "Clark Kent"]

Object.entries(family);
// ["father", "Jonathan Kent"]
// ["mother", "Martha Kent"]
// ["son", "Clark Kent"]

Object.values()は値のみの配列を返し、Object.entries()はキーと値の両方を含む配列の配列を返します。

7. Object.getOwnPropertyDescriptors()

このメソッドは、オブジェクトのすべてのプロパティ記述子を返します。
返すことができる属性はvalue, writable, get, set, configurable および enumerableです。

const myObj = {
  name: "Alberto",
  age: 25,
  greet() {
    console.log("hello");
  },
}
Object.getOwnPropertyDescriptors(myObj);
// age:{value: 25, writable: true, enumerable: true, configurable: true}

// greet:{value: ƒ, writable: true, enumerable: true, configurable: true}

// name:{value: "Alberto", writable: true, enumerable: true, configurable: true}

8. パラメータ列挙時における末尾カンマの許容

これは、構文の小さな変更です。
オブジェクトを書き込む時に、最後のパラメータであるかどうかに依らず、各パラメータの末尾にカンマをつけることができるようになります。

// こうだったのが
const object = {
  prop1: "prop",
  prop2: "propop"
}

// こうなる
const object = {
  prop1: "prop",
  prop2: "propop",
}

2番目のプロパティの最後にカンマを記述したことに注目してください。
入れなくてもエラーは発生しませんが、同僚やチームメンバーの生活を楽にする為に従うことをおすすめします。

// 私が書いたコードに・・・
const object = {
  prop1: "prop",
  prop2: "propop"
}

// 同僚がコードを更新し、新しいプロパティ prop3 を追加しますが・・・
const object = {
  prop1: "prop",
  prop2: "propop" // <- 末尾カンマがないよ!(構文エラー)
  prop3: "propopop"
}
// 直上のパラメータ prop2 の末尾にコンマを付け忘れた為、エラーになってしまいました

9. 共有メモリと Atomics(不可分操作)

MDNより:

不可分操作
メモリーが共有されている場合、複数のスレッドがメモリー内の同じデータを読み書きできます。
アトミック演算では、予測される値の書き込みと読み込みを保証するため、次の演算が開始される前に現在の演算が完了し、その演算が割り込まれないようにします。

Atomicsはコンストラクタではなく、そのプロパティとメソッドは(Mathと同様に)すべて静的です。
そのため、新しい演算子で使用したり、Atomicsオブジェクトを関数として呼び出すことはできません。

メソッドの例は次のとおりです。

  • 加算 add / 減算 sub
  • 論理積 and / 論理和 or / 排他的論理和 xor
  • 読み出し load / 格納 store

Atomicsメソッドの例をいくつか見てみましょう。

10. Atomics.add(), Atomics.sub(), Atomics.load() および Atomics.store()

Atomics.add()は、配列、インデックス、値の3つの引数を取ります。
インデックスで示された配列要素へ値を加算し、返り値として加算前の配列要素の値を返します。

// 共有メモリー上に配列バッファを用意します
// 訳者注: Spectre 型脆弱性から保護する為、SharedArrayBufferは主要ブラウザで無効化されています(Chromeについては一部例外あり)
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
const buffer = new SharedArrayBuffer(16);
const uint8 = new Uint8Array(buffer);

// 配列の先頭要素を追加します
uint8[0] = 10;

console.log(Atomics.add(uint8, 0, 5));
// 10

// 10 + 5 = 15
console.log(uint8[0])
// 15
console.log(Atomics.load(uint8,0));
// 15

ご覧のとおり、Atomics.add()は、ターゲットの配列位置で以前の値を返します。
その後、再度uint8[0]の内容を問い合わせると、加算演算が実行され、15が得られたことがわかります。

Atomics.loadに配列とインデックスの2つの引数を渡すことで、配列から特定の要素の値を取得できます。

Atomics.sub()Atomics.add()と同じ要領で機能し、値を減算します。

// 共有メモリーに配列バッファを用意します
const buffer = new SharedArrayBuffer(16);
const uint8 = new Uint8Array(buffer);

// 配列の先頭要素を追加します
uint8[0] = 10;

console.log(Atomics.sub(uint8, 0, 5));
// 10

// 10 - 5 = 5
console.log(uint8[0])
// 5
console.log(Atomics.store(uint8,0,3));
// 3
console.log(Atomics.load(uint8,0));
// 3

ここでは、uint8[0]の値10から5を減算するためにAtomics.sub()を使用しています。
Atomics.add()と同様に、メソッドはその配列要素の前の値(この場合は10)を返します。

次にAtomics.store()を、配列の特定要素(この場合はuint8[0])に、特定の値(この場合は3)を格納するために使用しています。
Atomics.store()は渡された値(この場合は3)を返します。

最後にAtomics.load()で同要素の値を読み出すと、5ではなく3が取得されることがわかります。

11. Atomics.and(), Atomics.or() および Atomics.xor()

これらの3つのメソッドはすべて、配列の特定要素の値に対して、ビット単位のAND、OR、XORの演算を実行します。
ウィキペディアのこちらのリンクでビット演算の詳細を読むことができます。

12. ES2017における Async と Await

ES2017では、「async / await」と呼ばれる Promise を操作する新しい方法を導入しました。

13. Promise の復習

この新しい構文に飛び込む前に、通常のPromiseを書く方法を簡単に確認しましょう。

// githubからユーザーデータを取得します
fetch('api.github.com/user/AlbertoMontalesi').then( res => {
  // 得られたデータをjson形式で返します
  return res.json();
}).then(res => {
  // もし上手くいったら、取得したデータを出力します
  console.log(res);
}).catch( err => {
  // どこかでダメだったら、エラーを出力します
  console.log(err);
})

これは、GitHubからユーザー情報を取得してコンソールに出力するという非常に単純な約束(Promise)です。

別の例を見てみましょう。

// 指定された時間歩きます(必ず歩くとはいってない)
function walk(amount) {
  return new Promise((resolve,reject) => {
    // 指定された時間が500ミリ秒未満なら、歩くのを却下します
    if (amount < 500) {
      reject ("値が小さすぎます");
    }
    // 指定された時間(ミリ秒)待ってから、指定されたメッセージを出力します
    setTimeout(() => resolve(`あなたは${amount}ミリ秒、歩きました`),amount);
  });
}

walk(1000).then(res => { // まずは1000ミリ秒歩いてみる
  console.log(res);
  return walk(500); // 上手くいったら、更に500ミリ秒歩く
}).then(res => {
  console.log(res);
  return walk(700); // 上手くいったら、更に700ミリ秒歩く
}).then(res => {
  console.log(res);
  return walk(800); // 上手くいったら、更に800ミリ秒歩く
}).then(res => {
  console.log(res);
  return walk(100); // 上手くいったら、更に100ミリ秒歩く
}).then(res => {
  console.log(res);
  return walk(400); // 上手くいったら、更に400ミリ秒歩く
}).then(res => {
  console.log(res);
  return walk(600); // 上手くいったら、更に600ミリ秒歩く
});

// あなたは1000ミリ秒、歩きました
// あなたは500ミリ秒、歩きました
// あなたは700ミリ秒、歩きました
// あなたは800ミリ秒、歩きました
// uncaught exception: 値が小さすぎます

それでは、新しい async / await 構文で上記のPromiseを書き換える方法を見てみましょう。

14. Async と Await

先ほどの例を、新しい構文で書き換えるとこうなります。

function walk(amount) {
  return new Promise((resolve,reject) => {
    if (amount < 500) {
      reject ("値が小さすぎます");
    }
    setTimeout(() => resolve(`あなたは${amount}ミリ秒、歩きました`),amount);
  });
}

// `async`キーワードを用いて非同期な関数を作ります
async function go() {
  // `await`キーワードを用いて非同期に応答を待ちます
  const res = await walk(500);
  console.log(res);
  const res2 = await walk(900);
  console.log(res2);
  const res3 = await walk(600);
  console.log(res3);
  const res4 = await walk(700);
  console.log(res4);
  const res5 = await walk(400);
  console.log(res5);
  console.log("finished");
}

go();

// あなたは500ミリ秒、歩きました
// あなたは900ミリ秒、歩きました
// あなたは600ミリ秒、歩きました
// あなたは700ミリ秒、歩きました
// uncaught exception: 値が小さすぎます

今やったことを分析しましょう。

  • 非同期関数を作成するには、その前にasyncキーワードを配置する必要があります
  • キーワードはJavaScriptが常にpromiseを返すように指示します
  • return を指定すると、promiseにラップされた値が返されます
  • awaitキーワードは唯一、非同期関数の内部でのみ動作します
  • その名前が示すように、awaitはpromiseが結果を返すまで待つようにJavaScriptに指示します

それでは、async付き関数の外でawaitを使用しようとするとどうなるか見てみましょう。

// awaitを普通の関数の中で使用してみます
function func() {
  let promise = Promise.resolve(1);
  let result = await promise; 
}
func();
// SyntaxError: await is only valid in async functions and async generators

// awaitを最上位空間で使用してみます
let response = Promise.resolve("hi");
let result = await response;
// SyntaxError: await is only valid in async functions and async generators

覚えておきましょう: awaitasyncの付いた非同期関数の中でしか使えません。

15. Promiseのエラーハンドリング

通常のPromiseでは、Promiseによって返される最終的なエラーをキャッチする為に.catch()を使用します。
ここでは、それほどの違いはありません。

async function asyncFunc() {

  try {
    let response = await fetch('http:your-url');
  } catch(err) {
    console.log(err);
  }
}

asyncFunc();
// TypeError: failed to fetch

エラーを取得する為にtry...catchを使いましたが、それを用いずとも、次のようにエラーをキャッチできます。

async function asyncFunc(){
  let response = await fetch('http:your-url');
}
asyncFunc();
// Uncaught (in promise) TypeError: Failed to fetch

asyncFunc().catch(console.log);
// TypeError: Failed to fetch

16. ES2018の新機能

ES2018で導入されたものを見てみましょう。

17. オブジェクトの rest / spread

ES6(ES2015)で以下のようなコードが書けるようになったことを覚えていますか?

const veggie = ["トマト","きゅうり",""];
const meat = ["豚肉","牛肉","鶏肉"];

const menu = [...veggie, "パスタ", ...meat];
console.log(menu);
// Array [ "トマト", "きゅうり", "豆", "パスタ", "豚肉", "牛肉", "鶏肉" ]

オブジェクトに対しても、 rest / spread 構文を使用できるようになりました。
次のコードを見てみましょう。

let myObj = {
  a:1,
  b:3,
  c:5,
  d:8,
}

// rest 演算子を使って、オブジェクトに残っている他の全てを取得します
let { a, b, ...z } = myObj;
console.log(a);     // 1
console.log(b);     // 3
console.log(z);     // {c: 5, d: 8}

// spread 構文を使って、オブジェクトのクローン(複製)を取得します
let clone = { ...myObj };
console.log(clone);
// {a: 1, b: 3, c: 5, d: 8}
myObj.e = 15;
console.log(clone)
// {a: 1, b: 3, c: 5, d: 8}
console.log(myObj)
// {a: 1, b: 3, c: 5, d: 8, e: 15}

Objectにspread演算子を使用すると、元のObjectを変更したときにも変更されないようなクローンを簡単に作成できます。
これは、配列について説明したときに見たものと同じです。

18. 非同期な反復(Async Iteration)

Async Iterationを使用すると、データに対して非同期に反復処理が行えます。

ドキュメントより:

非同期イテレータは、そのnext()メソッドが{ value, done }ペアの Promise を返すことを除いて、通常のイテレータによく似ています。

for-await-ofループを使用すると、残りが1つではない反復可能オブジェクトをPromiseに変換します。

const iterables = [1,2,3];

async function test() {
    for await (const value of iterables) {
        console.log(value);
    }
}
test();
// 1
// 2
// 3

実行中に、[Symbol.asyncIterator]()メソッドを使用してデータソースから非同期イテレータが作成されます。
シーケンスないの次の値にアクセスするたびに、イテレータメソッドから返されるPromiseを暗黙的に待機します。

19. Promise.prototype.finally()

Promiseの終了時に、コールバックを呼び出すことができます。

const myPromise = new Promise((resolve,reject) => {
  resolve();
})

myPromise
  .then( () => {
    console.log('まだ作業中です');
  })
  .catch( () => {
    console.log('エラーになっちゃいました');
  })
  .finally(()=> {
    console.log('作業完了!');
  })

.finally()もPromiseを返すので、より多くのチェーンを辿ってそれをキャッチできますが、それらのPromiseはチェーンされたPromiseに基づいて満たされます。

const myPromise = new Promise((resolve,reject) => {
  resolve();
})

myPromise
  .then( () => {
    console.log('まだ作業中です');
    return 'まだ作業中です';
  })
  .finally(()=> {
    console.log('作業完了!');
    return '作業完了!';
  })
  .then( res => {
    console.log(res);
  })
// まだ作業中です
// 作業完了!
// まだ作業中です

ご覧のとおり、finallyではなく、最初のthenによって作成されたPromiseの返り値が、finallyより後のthenにチェーンされます。

20. 正規表現の機能群

正規表現に関する4つの新しい機能が、新バージョンのECMAScriptに追加されました。
それらは以下のとおりです:

正規表現のsフラグ (dotAll)

ECMAScriptの正規表現が新たにsフラグを導入したことで、.は行終端記号を含む任意の文字に一致するようになります。

/foo.bar/s.test('foo\nbar');
// true

正規表現の名前付きキャプチャグループ

ドキュメントより:

番号付きのキャプチャグループを使用すると、正規表現が一致する文字列の特定の部分を参照できます。
各キャプチャグループには一意の番号が割り当てられ、その番号を使用して参照できますが、これにより正規表現の把握とリファクタリングが難しくなります。
たとえば、日付に一致する/(\d{4})-(\d{2})-(\d{2})/が与えられた場合、周囲のコードを調べずに、月に対応するグループと日に対応するグループを確認することはできません。
また、月と日の順序を入れ替えたい場合は、グループ参照も更新する必要があります。

キャプチャグループには、(?<name>...)構文を使用して任意の識別子名をnameに付けることができます。
日付の正規表現は、/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/uのように記述できます。
各識別子名は一意で、ECMAScriptの識別子名の文法に従う必要があります。
名前付きグループには、正規表現処理結果のgroupsプロパティにおける、識別子名のプロパティとしてアクセスできます。
名前のないグループと同様に、グループへの番号付き参照も作成されます。 例えば次のように:

let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';

// result[0] === '2015-01-02';
// result[1] === '2015';
// result[2] === '01';
// result[3] === '02';

let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
console.log(`one: ${one}, two: ${two}`); 
// one: foo, two: bar

正規表現の後読みアサーション

ドキュメントより:

後読みアサーションを使用すると、ドル記号をキャプチャせずにドル金額を一致させるといった感じで、パターンの前に別のパターンがあるかどうかを確認できます。
肯定的な後読みアサーションは(?<=...)として示され、アサーションに続くパターンの前に含まれるパターンを確実にします。
たとえば、ドル記号をキャプチャせずにドル金額を一致させたい場合は、/(?<=$)\d+(\.\d*)?/を使用して、'$10.53'と一致し、'10.53'を返します。
ただし、これは'€10.53'とは一致しません。
ネガティブな後読みアサーションは(?<!...)として示されますが、一方で、内部のパターンがアサーションに続くパターンの前にないことを確認してください。
たとえば、/(?<!$)\d+(?:\.\d*)/'$10.53'とは一致しませんが、'€10.53'とは一致します。

正規表現のUnicodeプロパティエスケープ

ドキュメントより:

これにより、\p{…}および\P{…}という形式のUnicodeプロパティエスケープが追加されます。
Unicodeプロパティエスケープは、uフラグが設定された正規表現で使用可能な、新しいタイプのエスケープシーケンスです。
この機能を使用すると、次のように記述できます。

const regexGreekSymbol = /\p{Script=Greek}/u;
regexGreekSymbol.test('π');
// true

21. テンプレートリテラルの制限の解除

タグ付きテンプレートリテラルを使用すると、エスケープシーケンスの制限がなくなります。

詳細はこちらをご覧ください。

22. ES2019の新機能

それではECMAScriptの最新バージョンであるES2019に含まれるものを見ていきましょう。

23. Array.prototype.flat() / Array.prototype.flatMap()

Array.prototype.flat()は、指定した深さまで配列を再帰的に平坦化します。
depth引数が指定されていない場合、1がデフォルト値です。
Infinityを使用すれば、すべてのネストされた配列をフラット化できます。

const letters = ['a', 'b', ['c', 'd', ['e', 'f']]];
// デフォルトの深さは1
letters.flat();
// ['a', 'b', 'c', 'd', ['e', 'f']]

// 深さ2を指定
letters.flat(2);
// ['a', 'b', 'c', 'd', 'e', 'f']

// これは、深さ1を指定して2回平坦化した場合と同じです
letters.flat().flat();
// ['a', 'b', 'c', 'd', 'e', 'f']

// ネストされた配列を含まない配列になるまで再帰平坦化を行います
letters.flat(Infinity)
// ['a', 'b', 'c', 'd', 'e', 'f']

Array.prototype.flatMap()は'depth'引数を処理する方法に関しては前のものと同じです。
しかし、配列を単純に平坦化する代わりに、flatMap()を使用してマッピングし、新しい配列を処理結果として返すこともできます。

let greeting = ["Greetings from", " ", "Vietnam"];

// まずは通常の`map()`関数を使用してみましょう
greeting.map(x => x.split(" "));
// ["Greetings", "from"]
// ["", ""]
// ["Vietnam"]

greeting.flatMap(x => x.split(" "))
// ["Greetings", "from", "", "", "Vietnam"]

ご覧のとおり、.map()を使用すると、複数階層の配列が得られます。
この配列を平坦化する為の手段として.flatMap()を使用できます。

24. Object.fromEntries()

Object.fromEntries()はkey-valueペアの配列をオブジェクトに変換します。

const keyValueArray = [
  ['key1', 'value1'],
  ['key2', 'value2']
]

const obj = Object.fromEntries(keyValueArray)
// {key1: "value1", key2: "value2"}

Object.fromEntries()の引数として、反復可能プロトコルを実装する配列、マップ、または他のオブジェクトのいずれでも、反復可能オブジェクトを渡すことができます。

反復プロトコルの詳細についてはこちらをお読みください:
https://developer.mozilla.org/ja-JP/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol

25. String.prototype.trimStart() / .trimEnd()

String.prototype.trimStart()は文字列の先頭から空白を削除します。
String.prototype.trimEnd()は末尾から空白を削除します。

let str = "    this string has a lot of whitespace   ";

str.length;
// 42

str = str.trimStart();
// "this string has a lot of whitespace   "
str.length;
// 38

str = str.trimEnd();
// "this string has a lot of whitespace"
str.length;
// 35

.trimLeft().trimStart()のエイリアスとして使用することができます。
.trimRight().trimEnd()のエイリアスとして使用することができます。

26. キャッチバインディングの補完(例外変数の省略)

ES2019より前は、常にcatch句に例外変数を含める必要がありました。
ES2019では、省略できます。

// 以前
try {
   ...
} catch(error) { // 例外変数の明記が必要
   ...
}

// ES2019
try {
   ...
} catch { // 例外変数を省略可能
   ...
}

これは、エラーを無視する場合に便利です。
この使用例の詳細なリストについては、こちらの記事を強くお勧めします。
http://2ality.com/2017/08/optional-catch-binding.html

27. Function​.prototype​.toString()

.toString()メソッドは、関数のソースコードを表す文字列を返します。

function sum(a, b) {
  return a + b;
}

console.log(sum.toString());
// function sum(a, b) {
//    return a + b;
//  }

コメントも含まれています。

function sum(a, b) {
  // 合計するよ
  return a + b;
}

console.log(sum.toString());
// function sum(a, b) {
//   // 合計するよ
//   return a + b;
// }

28. Symbol.prototype.description

.descriptionは、Symbolオブジェクトの任意の説明を返します。

const me = Symbol("Alberto");
me.description;
// "Alberto"

me.toString()
//  "Symbol(Alberto)"

29. チートシートをダウンロードする

翻訳元記事のチートシートはこのリンクからダウンロードできます。


最後までお読みいただきありがとうございます。
もし翻訳文章や内容についてお気づきの点があれば、コメント等でご連絡いただけると幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away