Getters と Setters は、変数の値を取得および設定するために使用する関数またはメソッドです。 ゲッター セッターの概念はコンピューター プログラミングでは一般的です。JavaScipt を含むほとんどすべての高レベル プログラミング言語には、ゲッターとセッターを実装するための一連の構文が付属しています。
Read Also: 知っておくべき 4 つの便利な JavaScript ステートメント
この投稿では、ゲッター セッターとは何か、そして JavaScript でそれらをどのように作成し使用するかを見ていきます。
ゲッター セッターとカプセル化
ゲッターとセッターのアイデアは常にカプセル化と一緒に言及されます。 カプセル化は2つの方法で理解することができます。
第一に、それはそのデータにアクセスし、変更するためのデータ-ゲッター-セッターのトリオを設定することである。 この定義は、保存または表示する前に、検証などのいくつかの操作をデータに対して実行する必要がある場合に有用であり、ゲッターとセッターはそのための完璧なホームを提供します。 このようにして、プログラム内の他のコードで重要なデータを誤って上書きすることがなくなります。
ゲッターとセッターの作成
1. メソッドを使用する
ゲッターとセッターは基本的に値を取得/変更する関数なので、それらを作成および使用する方法は 1 つだけではありません。 最初の方法は、
var obj = { foo: 'this is the value of foo', getFoo: function() { return this.foo; }, setFoo: function(val) { this.foo = val; }}console.log(obj.getFoo());// "this is the value of foo"obj.setFoo('hello');console.log(obj.getFoo());// "hello"
これは、ゲッターとセッターを作成する最も簡単な方法です。 プロパティ foo
があり、2つのメソッドがあります。
2. キーワードを使用する
ゲッターとセッターを作成する、より「公式」で堅牢な方法は、get
と set
キーワードを使用することです。
ゲッターを作成するには、ゲッターメソッドとして機能する関数宣言の前にget
キーワードを置き、同じ方法で set
キーワードを使って、セッターを作成します。 構文は以下の通りです:
var obj = { fooVal: 'this is the value of foo', get foo() { return this.fooVal; }, set foo(val) { this.fooVal = val; }}console.log(obj.foo);// "this is the value of foo"obj.foo = 'hello';console.log(obj.foo);// "hello"
ゲッター・セッターのメソッド名(foo
)とは異なるプロパティ名(fooVal
)でのみデータを格納できることに注意してください。ゲッター・セッターを保持するプロパティはデータをも保持できないためです。
どちらの方法が良いでしょうか?
キーワードでゲッターとセッターを作ることにすれば、通常のプロパティの値にアクセス/設定するのと同じように、データの設定には代入演算子を、データの取得にはドット演算子を使用することができます。
ただし、ゲッターとセッターをコーディングする最初の方法を選択した場合、セッターとゲッターのメソッドは典型的な関数であるため (get
や set
キーワードを使用して作成したもののように特別なものはない)、関数呼び出し構文を使用して呼び出さなければならない。
そこで、なぜ私が 2 番目の手法がより堅牢であると言ったか、おわかりいただけるでしょう。 Object.defineProperties
, Object.defineProperty
, Reflect.defineProperty
で作成されたプロパティは自動的に writable: false
に設定され、読み取り専用を意味します。
/* Overwrite prevention */var obj = { foo: 'this is the value of foo'};Object.defineProperties(obj, { 'getFoo': { value: function () { return this.foo; } }, 'setFoo': { value: function (val) { this.foo = val; } }});obj.getFoo = 66;// getFoo is not going to be overwritten!console.log(obj.getFoo());// "this is the value of foo"
Operations inside getters and setters
getters と setters を導入したら、データを変更または返す前にデータを操作することが可能です。
以下のコードでは、ゲッター関数ではデータが返される前に文字列に連結され、セッター関数ではn
を更新する前に値が数値であるかどうかの検証が行われます。
var obj = { n: 67, get id() { return 'The ID is: ' + this.n; }, set id(val) { if (typeof val === 'number') this.n = val; }}console.log(obj.id);// "The ID is: 67"obj.id = 893;console.log(obj.id);// "The ID is: 893"obj.id = 'hello';console.log(obj.id);// "The ID is: 893"
ゲッターとセッターによるデータの保護
これまで、カプセル化の最初のコンテキストでゲッターとセッターの使用について説明しました。 2 番目のコンテキスト、つまり、ゲッターとセッターの助けを借りて外部のコードからデータを隠す方法について説明します。
Unprotected data
ゲッターとセッターを設定しても、データがそれらのメソッドを通じてのみアクセスおよび変更できるわけではありません。 次の例では、ゲッターやセッターのメソッドに触れずに直接変更しています。
var obj = { fooVal: 'this is the value of foo', get foo() { return this.fooVal; }, set foo(val) { this.fooVal = val; }}obj.fooVal = 'hello';console.log(obj.foo);// "hello"
セッターを使用せずに直接データを変更しました(fooVal
)。 obj
の中に最初に設定したデータは、もうなくなってしまいました このようなことが(誤って)起こらないようにするためには、データを何らかの形で保護する必要があります。 データが利用できる範囲を限定することで、それを追加することができます。 ブロックスコープまたは関数スコープのどちらかを使用することができます。 ブロック スコープ
1つの方法は、そのブロックに範囲を限定する let
キーワードを使用して、データが定義されるブロック スコープを使用することです。 ブロック スコープを作成するときは常に、中括弧をそのままにしておくよう求めるコメントをその上に残してください。そうすれば、中括弧をコード内の余分な中括弧だと思って間違って削除したり、ブロック スコープにラベルを追加する人がいないでしょう。 Function scoping
スコープでデータを保護するより一般的な方法は、データを関数内に保持し、その関数からゲッターとセッターを持つオブジェクトを返すことです。
function myobj(){ var fooVal = 'this is the value of foo'; return { get foo() { return fooVal; }, set foo(val) { fooVal = val } }}fooVal = 'hello';// not going to affect our original fooValvar obj = myobj();console.log(obj.foo);// "this is the value of foo"
myobj()
関数が返すオブジェクト (その中に foo()
ゲッター・セッターを含む) は obj
に保存され、次に obj
がゲッターとセッターの呼び出しに使われます。
3 スコープなしのデータ保護
また別の方法で、範囲を限定せずにデータの上書きを防ぐことも可能です。 その論理は次のようなものです。「何が呼び出されているのかわからないのに、どうやってデータの一部を変更できるのか」
データにそれほど簡単に再現できない変数/プロパティ名がある場合、その変数/プロパティ名に何らかの値を代入して上書きしてしまう人は、(私たちでさえ)誰もいない可能性があります。 私が選んだ名前はあまり良いものではありませんが、Derick Baileyがこのブログ記事で提案しているように、ランダムな値や記号を使ってプロパティ名を作成することもできます。 主な目標は、データを他のコードから隠しておき、ゲッターとセッターのペアでアクセス/更新できるようにすることです。
いつゲッターとセッターを使用すべきか
さて、大きな疑問があります。
データを隠している場合、他の選択肢はありません。
しかし、他のコードによって見られるデータが問題ない場合、そのデータに対して何らかの処理を実行するコードにバンドルするためだけにゲッター セッターを使用する必要があるでしょうか。 私は「はい」と答えます。 コードはすぐに増えてしまいます。 独自のゲッター セッターを持つ個々のデータのマイクロユニットを作成すると、コードの他の部分に影響を与えることなく前記データで作業するための一定の独立性が得られます。