Getters and Setters in JavaScript

Mosh Hamedani

Follow
Dec 29, 2019 – 5 min read

ゲッターとセッターという概念は、現在使われている一般的な言語ではかなり一般的なものです。 オブジェクトのプロパティに何らかの値を代入する前または後に、与えられたアクションが常に実行されるようにする必要があったことがありますか? これはセッターを使えば可能です。 また、ゲッターを使えば、プロパティの値を取得する際に何らかの処理を行うことができます(例えば、フォーマットなど)。 ゲッターとセッターを実装する方法として、Javaで行われているようにメソッドを使用する方法があります。 しかし、ES5以降では、getsetの構文を使用することで、よりエレガントで実用的な代替手段を利用することができるのです。 さて、始めましょう!

JavaScript では、オブジェクトはプロパティのコレクションであり、おそらくデータを保存するために使用したことがあるはずです。 プロパティは単にキーと値のペアです。 以下はその例です。

const options = {
timeout: 5000,
retries: 3,
ip: '192.168.1.20',
port: 4001,
};

オブジェクト内のプロパティは、このように簡単に設定したり読み取ったりできます。

artist.name = 'Carice Anouk van Houten';console.log(artist.name); //=> "Carice Anouk van Houten"

繰り返しますが、すでに JavaScript を使ったことがあるなら、これは間違いなく新しいことではありません。 これらの通常のプロパティとこの記事で紹介する他のタイプを区別するために、前者を「データ プロパティ」と呼ぶことができます。

Getters and setters: the old way

ES5 以前は、ゲッターとセッターを実装するには、通常のメソッドを使用するしか方法はありませんでした。 以下の例のように:

ここでは、魔法がないことを明確にするために、上記の例で関数キーワードを保持しました。 通常のメソッドのみです。 ES2015 のメソッド定義構文を使用しても同じ効果を得ることができましたが、これはより短く、いくぶんエレガントです。

config.setPort(8080);
console.log(config.getPort()); //=> 8080

値のインクリメントは次のように行われます:

item.setQuantity(item.getQuantity() + 1);

プロパティを直接インクリメントする場合と比較して、非常に冗長に見えます:

item.quantity += 1;
// Or even simpler...
item.quantity++;

Getters and setters: どうしてですか?

Java や C++、C# などの OO 言語では、アクセス修飾子 (publicprotectedprivate など) を使用して、異なるレベルでクラスのメンバーを公開することが可能です。 これは、データ隠蔽と呼ばれる OOP の重要な概念を実装するのに役立ちます。

これらの言語におけるゲッターとセッターの非常に一般的な使用法は、安全な方法でクラスのメンバーを公開することです。 例えば、プライベートなメンバがクラスの外から決して変更されないようにするためにゲッターだけを実装することができます。

JavaScript ではどうでしょうか。

JavaScript では、状況は少し異なります。 この記事を書いている時点では、JS にはアクセス修飾子がありません。 現在、私たちが持っている最良の選択肢は、キーとして使用されたときにある程度のプライバシーを与える、シンボルを使用することです。 しかし、それを好まない人もいます。 特に、リフレクションを使用すると、このプライバシーを簡単に破ることができるからです。

リフレクションがある言語は通常、プログラマが何らかの方法でカプセル化を破ることができるので、私はこれを本当の問題だとは思っていません。 私が考えるシンボルの問題は、単純なプライベートアクセッサがそうであるように、シンボルを使用することはそれほど実用的ではないということです。 良いニュースは、プライベートフィールドを含むEcmaScriptの提案がすでにステージ3に入っていることです。 そして、それらはいかなる種類のリフレクションに対しても免疫があるでしょう。

前のセクションの例では、プライベートメンバーをシミュレートするためにシンボルや他のトリックを使いませんでした。 _port プロパティはそれ自体何も特別なものを持っていません。

シンボルやその他のカプセル化テクニックの説明はこの記事の目的ではないので、コード例ではプライベート プロパティは実装していません。 ただ、ゲッターとセッターはカプセル化されたメンバーへのアクセスを提供するために一般的に使用されることを覚えておいてください (ただし、常にではありません)。 最後に、_portプロパティの名前の前にアンダースコアがあることに注意してください。 これは JS 開発者の間で事実上の慣習となっており、与えられたプロパティがプライベートであり、それが定義されているクラスの外からアクセスされるべきではないことを示します。

ゲッターとセッター: アクセサ プロパティによる新しい方法

アクセサ プロパティは、ゲッターとセッターを定義する現代的な方法です。 その定義に関しては、以前の例とそれほど変わりませんが、本当に異なるのはその使用方法です。

ご覧のように、この例では 2 つの点だけが変更されています。

  • setPortgetPort のメソッドを持つ代わりに、アクセッサ プロパティを使用するようにコードを調整します。 setget 構文を使用し、プロパティには単一の名前 (この例では “port“) を使用します。
  • ここで function キーワードは必要ありません。 実際、これを使用しようとすると、SyntaxError が発生します。

アクセサ プロパティを使用するには?

アクセサ プロパティの定義が、古い学校のゲッターとセッターの作成方法と非常に似ていると、その使用方法は、通常のデータのプロパティの使用方法と目に見える違いがありません:

config.port = 8080;
console.log(config.port); //=> 8080

そしてインクリメント式は、次のように見えます:

timer.seconds += 1;

そうですね。 とても簡単ですね。=)

Conclusion

  • オブジェクトはプロパティのコレクションです
  • 通常のプロパティは単なるキーと値のペアで、「データ プロパティ」と呼ぶことができます
  • ゲッターとセッターは通常の方法として実装できます。 これはJavaScriptの「古い学校」の方法です。
  • ゲッターとセッターは通常、クラスのプライベートメンバーへのアクセスを提供するために使用されます。
  • アクセサプロパティは、古い通常のメソッドベースのゲッターとセッターとまったく同様に動作できますが、その使用法はデータプロパティのように見えるように作られています。

Do you want to master JavaScript? MoshのJavaScriptコースを強くお勧めします。

そして、もしこの記事が気に入ったら、他の人とシェアしてください!

コメントを残す

メールアドレスが公開されることはありません。