2020.12.09
ざっくり ECMAScript 2019
ざっくりと ES2019 のおさらいをしたい人向け。オカタい説明は mdn さんあたりにおまかせするとして、ゆるっとざっくり気楽にサクッとおさらい。ES2019 は try-catch 構文の仕様変更、String.prototype.trimStart、String.prototype.trimEnd、Array.prototype.flat、Array.prototype.flatMapが追加されたよ
環境構築
- MacOS High Sierra
- ふる〜い MBP 使ってます
- nvm, ndenv, nodebrew のどれでもいいので node が動く環境を用意
- VSCode 使ってます。拡張はお好みで。
- node.js のバージョンは v14.7.0
- 適当なディレクトリを掘って、index.js を用意しています (ファイル名はお好みで)
- 動作確認は $ node index.js って叩いてます
最小限で動かすだけならこれだけでおっけいです。ここらへんの準備も面倒ならば codepen だの JSFiddle だの REPL だのを使ってもおk
es2019
es2019 は以下のような機能が追加されている:原文(参考 github tc39/proposals finished-proposals)
Optional “catch” binding、JSON superset、Symbol.prototype.description、Function.prototype.toString revision、Object.fromEntries、Well-formed JSON.stringify、String.prototype.{trimStart,trimEnd}、Array.prototype.{flat,flatMap}
Optional catch binding(”try-catch” syntax changes)
try-catch 構文変更として、以下のようにキャッチバインディングとその周辺の括弧を省略することができるようになったよ
1 2 3 4 5 6 7 |
const returnExeption = () => { throw new Error("hoge") } try{ returnExeption() }catch{ console.log("error") } |
JSON superset (github 原文ママ)
JSON構文はECMA-404で定義され、RFC 7159で恒久的に固定されていますが、ECMA-262のDoubleStringCharacterとSingleStringCharacterの生成物は、エスケープされていないU+2028 LINE SEPARATORとU+2029 PARAGRAPH SEPARATOR文字を許可するように拡張することができます。
以下のコードはエラーにならなくなった。
1 2 |
const PS = eval("'\u2029'"); const LS = eval("'\u2028'"); |
Symbol.prototype.description
Symbol の説明を Symbol.prototype.toString を通してではなく、直接 desription でアクセスできるよ
1 2 3 4 5 6 7 |
const s = Symbol("Hey") console.log(s.toString()) console.log(s.description) // Symbol(Hey) // Hey |
Function.prototype.toString revision
とりあえず原文
The original goals of this proposal were
- remove the forward-incompatible requirement
If the implementation cannot produce a source code string that meets these criteria then it must return a string for which eval will throw a SyntaxError exception.- clarify the “functionally equivalent” requirement
- standardise the string representation of built-in functions and host objects
- clarify requirement of representation based on the “actual characteristics” of an object
The goals were later revised to include
- ensure that the string’s parse contains the same function body and parameter list as the original
The goals were revised again to include
- for functions defined using ECMAScript code, toString must return source text slice from beginning of first token to end of last token matched by the appropriate grammar production
- for built-in function objects and bound function exotic objects, toString must not return anything other than NativeFunction
- for callable objects which were not defined using ECMAScript code, toString must return NativeFunction
- for functions created dynamically (through the Function and GeneratorFunction constructors), toString must synthesise a source text
- for all other objects, toString must throw a TypeError exception
The goals were revised yet again to include
- implementations must not be required to retain source text for all functions defined using ECMAScript code
翻訳
この提案の本来の目的は
- 前方互換性のない要件を削除する
実装がこれらの基準を満たすソースコード文字列を生成できない場合は、eval が SyntaxError 例外を投げるような文字列を返さなければなりません。- 「関数的に等価」という要件を明確にしました。
- 組み込み関数とホストオブジェクトの文字列表現を標準化します。
- オブジェクトの「実際の特性」に基づく表現の要件を明確にする
目標はその後、以下のように修正されました
- 文字列のパースでは、元の文字列と同じ関数本体とパラメータリストが含まれていることを確認します。
目標は以下のように再改定されました。
- ECMAScript コードを使用して定義された関数の場合、toString は、最初のトークンの先頭から最後のトークンの末尾までの、適切な文法プロダクションにマッチするソーステキストのスライスを返さなければなりません。
- 組み込みの関数オブジェクトとバインドされた関数のエキゾチックオブジェクトの場合、toStringはNativeFunction以外のものを返してはいけません。
- ECMAScript コードで定義されていない呼び出し可能なオブジェクトの場合、toString は NativeFunction を返さなければなりません。
- 動的に作成された関数 (Function および GeneratorFunction コンストラクタを介して) の場合、toString はソーステキストを合成しなければなりません。
- 他のすべてのオブジェクトの場合、toString は TypeError 例外をスローしなければなりません。
といった目標を改めて修正しました。
- ECMAScript コードを使用して定義されたすべての関数のソーステキストを保持する必要はありません。
めっちゃわかりにくいし、タイトル通りなんだけど要するに「関数オブジェクトに対して toString() を実行した時の挙動を定義」したっぽい。詳しくはこっちを見て。
Object.fromEntries
Object.fromEntriesは、反復可能なキーと値のペアを受け取り、それらのペアによってキーとそれに対応する値が与えられた新しいオブジェクトを返します(意訳)
次のコードでは、配列に [ key, value ] を想定する配列を引数として渡した例です。
1 2 3 4 |
const obj = Object.fromEntries([['a', 0], ['b', 1]]); // { a: 0, b: 1 } console.log(obj) // { a: 0, b: 1 } |
Well-formed JSON.stringify
乱暴な説明で申し訳ないけど、JSON.stringify が不正な Unicode 文字(列)を返さないようになったよ。JIS第3水準、JIS第4水準の漢字と戦っている人とかUnicode周りで頑張っている方には朗報?(笑)
前々までは文字化けっぽくなってたのが、ちゃんとエスケープされたりするんだけど、Wordpress もろもろ弾かれちゃうので実際に実行してみて。
1 2 3 |
// Non-BMP characters still serialize to surrogate pairs. console.log(JSON.stringify('\uD834\uDF06')) console.log(JSON.stringify('\uD842\uDFB7')) |
もっと深く突っ込みたい人向けの検索ワード
- サロゲートペア
- JIS第三水準、JIS第4水準
- Unicode
- github 原文 Well-formed JSON.stringify:tc39/proposal-well-formed-stringify
String.prototype.{trimStart,trimEnd}
先頭、もしくは末尾の空白を取り除くことができるメソッドが追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 前後3つのスペース const str = ' content ' console.log(str.trimStart()) console.log(str.trimStart().length) // "content " // 10 console.log(str.trimEnd()) console.log(str.trimEnd().length) // " content" // 10 |
Array.prototype.{flat,flatMap}
配列 や Map をフラットにすることができるメソッドが追加されたよ
Array.prototype.flat
フラットにするのは、ネストしている配列の1階層分。ネストされたものまでは及ばない。
1 2 3 4 5 6 7 8 9 10 |
const arr1 = [1, 2, [3, 4]] const arr2 = [1, 2, [3, [4, 5]]] console.log(arr1.flat()) console.log(arr2.flat()) console.log(arr2.flat().flat()) // [ 1, 2, 3, 4 ] // [ 1, 2, 3, [ 4, 5 ] ] // [ 1, 2, 3, 4, 5 ] |
Array.prototype.flatMap
flatMap は、一度マッピングした後にフラットにするよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
const arr = [1, 2, 3, 4, 5] const users = [ { name: 'taro', age: 20 }, { name: 'jiro', age: 18 }, { name: 'subro', age: 17 } ] console.log(arr.flatMap( v => v * 2)) console.log(users.flatMap( v => v.name )) // [ 2, 4, 6, 8, 10 ] // [ 'taro', 'jiro', 'subro' ] |