2022/6/27(月)に開催された「Node学園 39時限目 オンライン Node.js の原罪と現在」における、私の発表資料です。
https://nodejs.connpass.com/event/250782/
Node学園 39時限目ES2022の新機能Author: Masaki Suzuki@makky12
View Slide
自己紹介• 名前:鈴木 正樹 (Masaki Suzuki)• 在住:愛知県半田市• 職業:フリーランスエンジニア• 得意分野:サーバーレスアプリのバックエンド(アーキ構築/設計/開発など)• 技術:• AWS/Serverless Framework/Terraform/AWS CDK/サーバーレス全般• Node.js/TypeScript/Jest/Next.js/Haxe/GCP/Azure• 各種イベント・SNS・ブログでのクラウド普及活動(個人的に)• SNS:http://makky12.hatenablog.com/https://github.com/smt7174@makky12 (SUZUKI Masaki@クラウドエンジニア)名古屋市豊橋市Node学園 39時限目
本日紹介する新機能• クラス関連の新機能• 基本機能• プライベート要素の有無判定(Ergonomic brand checks for private fields)• クラス以外の新機能• Top-level await• .at() method on the built-in indexables• Error.cause property• RegExp Match Indices• Object.hasOwnNode学園 39時限目
参考資料・サイト• 【参考情報】• node.green• 【ブログ】• JavaScriptの次の仕様ES2022の新機能まとめ• 【JavaScript】ES2022の新機能• 【JavaScript】ES2022で正式採用される機能について本日の発表資料は、以下の場所で公開してます• https://speakerdeck.com/smt7174/es2022noNode学園 39時限目
Node学園 39時限目クラス関連の新機能
クラス関連• クラス関連の新機能として、下記に正式対応した関数• クラスフィールドの作成• 静的(static)な要素の作成• 静的メソッド/静的フィールドどちらも作成可能• privateな要素の作成• これもprivateメソッド/privateフィールドどちらも作成可能• チームでのルール決めでの対応が不要に• クラスの基本的な部分が、やっと普通に使えるようになった感じ• protectedなど、未対応な部分もあるが…Node学園 39時限目
クラス関連(ソースコード)Node学園 39時限目class A {// クラスフィールドx = 1; // publicなクラスフィールドstatic sx = 2; // staticをつけると静的(static)フィールドに#y = 3; // #をつけるとprivateなクラスフィールドにstatic #sy = 4; // privateな静的フィールドも作成可能constructor() {}// クラスメソッドpublicFunc() {}static staticPublicFunc() {} // staticをつけると静的(static) メソッドに#privateFunc() {} // #をつけると静的(static) メソッドにstatic #staticPrivateFunc() {} // privateな静的(static) メソッド}
クラス関連2• privateな要素の存在有無を「in」でチェックできる• クラスレベルで判定する• 該当クラスのprivateな要素を持っているか判定• 主な使用用途は、インスタンスの等価チェック?• a instanceof b みたいな使用方法• 今のところ、良い使用用途がいまいち不明…• 今回クラスフィールド対応が追加されたのもあるのでNode学園 39時限目// ソースコードclass A {#x = 1;constructor(x = null) { if (x) #x = x; }static isA(obj) {return #x in obj;}}class B {#x = 1;constructor() {}}console.log(A.isA(new A())); // trueconsole.log(A.isA(new B())); // falseconsole.log(A.isA(new A(2))); // true(値そのものは問わない)
Node学園 39時限目クラス以外の新機能
Top-level await• 最上位ソースのみ、直接awaitすることができる• async, Promise.then()などが不要に• モジュールファイルのみ対応(*.mjsなど)• あくまで「最上位ソース」のみが対象• 関数内などでは、今まで通りasyncが必要• asyncが完全に不要になったわけではないNode学園 39時限目// ソースコード//これはNG(関数など最上位ソース以外は、asyncが必要)function badSampleAsync() {return await SampleFuncAsync();}//これはOKconst result = await badSampleAsync();console.log(result);
.at() method on the built-in indexables• 変数.at(index)で、変数[index]の要素にアクセスできる• 文字列、または配列が対象• indexに負数を指定することで、末尾からの要素を指定できる。(-1が末尾要素)• String.substr(index)と同じ• 末尾要素を指定するのが簡単になった• array[array.length - 1] みたいな指定が不要になったNode学園 39時限目// ソースコードconst str = ‘abcdefg’;const array = [‘hoge’, ‘fuga’, ‘piyo’];// これは今までもできたconsole.log(str.at(0)); // aconsole.log(array.at(1)); // fuga// 負数の指定は.at()からできるようになったconsole.log(str.at(-3)); // econsole.log(array.at(-1)); // piyo
Error.cause property• Errorクラスに発生源をたどるプロパティ「cause」が追加された• 「cause」プロパティ自体はオプショナル• 親子関係(=依存関係)があるコードで、エラーの発生源をたどるのに便利• 「error.cause」プロパティで、発生源のエラー(Error)を参照できる• 子孫要素が多くなると、複数のcauseをたどる必要がある• 「error.cause.cause.cause…」のような感じ• 発生源のエラーを見つける専用の関数などを用意した方が良いかも• そもそも、そこまで依存関係が多いこと自体が問題かもしれないが…Node学園 39時限目
Error.cause property(ソースコード)Node学園 39時限目function parent() {try {child();} catch (e) {// ここのeはchild()からthrowされたもの。console.log(`e is ${e.message}`);console.log(e.cause.message);}}function child() {try {grandChild();} catch (e) {// ここのeはgrandChild()からthrowされたもの。// 発生源にe(=grandChild Error)を指定throw new Error("child Error", {cause: e});}}function grandChild() {// ここがエラー発生源throw new Error("grandChild Error",);}parent();// 結果はこうなるe is child Error // console.log(`e is ${e.message}`)の結果grandChild Error // console.log(e.cause.message)の結果
RegExp Match Indices• 正規表現パターンマッチングで一致文字の開始&終了位置を取得できる• 「d」フラグを付けることで可能• 「indices」プロパティ(配列)のindex:0に配列形式で格納される• indices:[[開始位置, 終了位置]] のような感じ• 終了位置は、一致文字列の最終文字のindex+1が入る。(String.slice()の引数と同じ)• キャプチャグループがある場合、indices[1] 以降に同様の形式で格納されるNode学園 39時限目// ソースコード// キャプチャグループなしconst result = /cd/d.exec(‘abcdefabcdefg’);console.log(result.indices); // [ [2, 4], groups: undefined ]// キャプチャグループありconst result = /cd(ef)/d.exec(‘abcdefabcdefg’);console.log(result.indices); // [ [2, 6], [4, 6], groups: undefined ]
Object.hasOwn• Object.hasOwn(obj, key)でオブジェクトが該当キーを持っているかを確認できる。• 挙動自体はObject.hasOwnProperty(obj, key)と同じ• Object.prototype.hasOwnProperty.call(obj, key)のショートハンド• 上記指定だと長いので、そのためかと思われる• Object.hasOwnProperty()によるプロトタイプ汚染問題の対応もあるNode学園 39時限目// ソースコードconst obj ={x: 10,y: 20,};console.log(Object.hasOwn(obj, ‘x’)); // trueconsole.log(Object.hasOwn(obj, ‘z’)); // false
まとめ(個人的な感想)• クラスに関しては「やっと普通に使えるようになった」感じ• 特にクラスフィールド、private要素あたり• private要素に関しては、チームでのルール決めがこれで不要になった• (_から始めるのはprivateな扱い…など)• クラス以外に関しては「大きな変更はないが、地味な部分で便利になった」印象• 去年の発表(「Node.js16の新機能」)と全く同じだな…• でも個人的に、top-level-awaitやxxx.at(index)はありがたいという感想Node学園 39時限目
以上ですご清聴ありがとうございましたNode学園 39時限目