ES2022の新機能についてまとめた
はじめに
先日ES2021までの新機能についてまとめた以下記事を公開しました。本記事ではES2022についてまとめています。
他記事を参考に、自分が見返したときに理解できるようにまとめた記事になりますので、もし不足事項等あればご指摘ください。
前回の記事はこちらです。
前回同様こちらの記事を参考にしています。
ES2022
トップレベル await
ES2022以前では、awaitはasync宣言した関数内でしか使うことができませんでした。
ES2022ではasync宣言なしでトップレベルにおいてawaitを使うことが可能です。
※モジュール内でのみ使用可能です。関数内ではawait宣言が必要です。
await getHogeData();
クラスフィールド宣言
ES2022では、コンストラクタ中で宣言する必要がなくなりました。
// before
class Counter {
constructor() { // constructor内で定義が必要
this.count = 0;
}
countUp() { this.count++; }
}
// after
class Counter {
count = 0;
countUp() { this.count++; }
}
プライベートフィールド・プライベートメソッド
ES2022以前、クラスフィールドはクラス外部からアクセスできてしまうパブリックなものしかありませんでした。
先頭に_
をつけることで、プライベート扱いにしていました。
class Counter {
constructor() { this._count = 0 }
countUp() { this._count++; }
count() { return this._count; }
}
var counter = new Counter();
counter.countUp();
console.log(counter.count()); // count()はプライベートではないのでアクセス可能
console.log(counter._count); // _countは先頭に_があるためプライベート扱いだが、アクセス可能
ES2022では、先頭に#
をつけることで、プライベートフィールドであることを明確に宣言可能になりました。
class Counter {
#count = 0;
countUp() { this.#count++; }
count() { return this.#count; }
}
var counter = new Counter();
counter.countUp();
console.log(counter.count()); // count()はプライベートではないのでアクセス可能
console.log(counter.#count); // #countはプライベートなのでアクセス不可→エラー
また、メソッドについても#
をつけることでプライベート宣言が可能です。
class Counter {
#count = 0;
countUp() { this.#count++; }
#count() { return this.#count; }
}
static イニシャライズブロック
staticフィールドの値を変更する場合、クラス定義の外に記述する必要がありました。
class Foo {
static x = 123.4;
static y;
}
Foo.y = Foo.x * 2;
ES2022以降では、staticイニシャライザを使うことでクラス定義内で記述可能になりました。
class Foo {
static x = 123.4;
static y;
static {
Foo.y = Foo.x * 2;
}
}
こちらの記事を参考に理解しました。
プライベートフィールドに対する in 演算子
あるオブジェクトがインスタンスであるかどうかはinstanceof
を使い調べることが可能です。
class Foo { }
foo = new Foo();
console.log(foo instanceof Foo);
ただし、setPrototypeOf
を使った場合、インスタンスではないのにinstanceof
を使って調べた結果がtrueになってしまうことがありました。
class Foo { }
class Baa { }
foo = new Foo();
baa = new Baa();
Object.setPrototypeOf(baa, foo);
console.log(baa instanceof Foo); // true
Object.setPrototypeOf() メソッドは、指定されたオブジェクトのプロトタイプ (つまり、内部の [[Prototype]] プロパティ) を、別のオブジェクトまたは null に設定します。
instanceof 演算子は、あるコンストラクターの prototype プロパティが、あるオブジェクトのプロトタイプチェーンの中のどこかに現れるかどうかを検査します。
そのため、「プライベートフィールドである#brand にアクセスできるのは Foo のインスタンスのみである」ということを利用してインスタンスかどうかを調べる、ブランドチェックというテクニックが考案されました。
class Foo {
#brand;
static isFoo(obj) {
try {
obj.#brand;
return true;
} catch {
return false;
}
}
}
class Baa { }
foo = new Foo();
baa = new Baa();
Object.setPrototypeOf(baa, foo);
console.log(Foo.isFoo(baa)); // false
これを簡略化したものがin
を使う方法です。
class Foo {
#brand;
static isFoo(obj) {
return #brand in obj;
}
}
class Baa { }
foo = new Foo();
baa = new Baa();
Object.setPrototypeOf(baa, foo);
console.log(Foo.isFoo(baa)); // false
正規表現の d フラグによる開始・終了インデックス
正規表現に、マッチした部分文字列の開始・終了インデックスを得るためのd
フラグが追加されました。
以下の場合、1つ目のindexには文字列全体の開始・終了インデックス、2つ目には1個目のマッチ文字列の開始・終了インデックスが入ります。
const result = "My name is Yamada".match(/My name is (.*)/d);
console.log(result); // ["My name is Yamada", "Yamada"]
console.log(result.indices); // [Array [0, 17], Array [11, 17]]
Error.cause によるエラーチェイン
なんらかの処理を持つfuncAとfuncBが存在し、funcXでは両方の処理を実行できるようにします。
このとき、以下のように記述可能ですが、例外が発生した場合に、funcAとfuncBどちら起因なのかわかりませんでした。
function funcX() {
try {
funcA();
funcB();
} catch (e) {
throw new Error("FuncX() is failed.");
}
}
ES2022では、cause
パラメータを使用し、例外情報を得ることが可能になりました。
function funcX() {
try {
funcA();
funcB();
} catch (e) {
throw new Error("FuncX() is failed.", { cause: e });
}
}
try {
funcX();
} catch (e) {
console.log(e); // FuncX() is failed.
console.log(e.cause); // funcB() is failed.
}
at(-n)で最後からN番目の要素を取得
ES2022ではat
を使うことで、最後からN番目の要素を簡潔に取得可能になりました。
const foo = ["Red", "Green", "Blue"];
console.log(foo[foo.length - 1]); // Blue
console.log(foo.at(-1)); // Blue
hasOwn() によるプロパティ保持チェック
オブジェクトが特定のプロパティを保持しているかを判断するとき、Object.prototype.hasOwnProperty.call(obj, prop)
の代わりにObject.hasOwn(obj, prop)
が使用できるようになりました。
Object.prototype を汚染するコードを記載していた場合や、hasOwnPropertyというメソッドがあった場合も簡潔にプロパティ保持チェックを行うことが可能です。
こちらについては以下の記事を読み、理解できましたので貼付しておきます。
まとめ
ES2021までに追加された機能に対し、ES2022の新機能は知らないものが多かったです。
また業務上ではあまり使っていないクラス周りの知識を得ることができてよかったです。
次回はES2023についてまとめたいと思います。
Discussion