JavaScriptのクラスのプライベートについて

オライリーのNode.jsハンズオンの本を読んでいたら、知らないことがあったため、備忘録として書きます。(忘れなさそうだけど)

気になる人は以下のリンクから確認してください。

ハンズオンNode.js 今村 謙士 https://www.amazon.co.jp/dp/4873119235/ref=cm_sw_r_tw_dp_0WX0N6D9C2P64S7BSMFP @amazonJPより

朝で頭が回らなかったのであっさり文章です。

今まで書いていたもの

普段、僕がJavaScriptのクラスでプライベートなプロパティやメソッドを作成する際には、下のような感じで書いてます。

class Foo {
    _prop = 'foo';

    get prop() {
        return this._prop;
    }

    set prop(value) {
        this._prop = value;
    }
}

const a = new Foo();
console.log(a.prop);
a.prop = 'bar';
console.log(a.prop);

/*
> foo
> bar
*/

実際にこんな感じで書いている人はいるはずです。自分はネットでこういう書き方があるって知った身です。

この問題としては、厳密にプライベートメソッドではないという点です。クラス外でもプロパティやメソッドを指定することで、取得・変更・実行することが出来てしまいます。

console.log(a._prop);

/*
> bar
*/

今回知ったもの

今回知ったプライベートの方法は、「#」を使う方法です。具体的な方法は見た方が早いので下に書きます。

class Foo {
    #prop = 'foo';

    get prop() {
        return this.#prop;
    }

    set prop(value) {
        this.#prop = value;
    }
}

const a = new Foo();
console.log(a.prop);
a.prop = 'bar';
console.log(a.prop);

/*
> foo
> bar
*/

これによって、プロパティ・メソッドをプライベートにすることが出来ます。先ほどの方法とは違い、クラス外でプロパティ・メソッドの取得・変更・実行することが出来ません。

これに無理にアクセスしようとすると下のようになります。

console.log(a.#prop);

/*
/workspace/Main.js:22
console.log(a.#prop);
             ^

SyntaxError: Private field '#prop' must be declared in an enclosing class
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47
*/

問題点としては、MDNのサイトでこのプライベートクラスフィールドについて、「実験的な提案」と書かれている点です。一部ブラウザでサポートされていない、古いNodeのバージョンで対応していないなど、問題がいくらかあるため、あまり多用するべきではないかもしれません。

プライベートクラスフィールド - JavaScript | MDN

補足

この「#」によるプライベートですが、古いバージョンのNode.jsでは実行できませんでした。自分はv12.15.0で実行して、#をつけたメソッドでエラーが発生しました。もし動作できない環境で使いたいなら、Nodeのバージョンを更新しましょう(特に問題なければの話)。

無関係な話

最近、就活が始まってからあまり時間が取れないように感じます。やりたいこと・やらなければならないこと・やるべきことの区別と分配が必要そうです。