December 23, 2013
ほとんどの場合、JavaScriptでは、あなたが見るものはあなたが得るものである。 値は値であり、トリックはありません。 たとえば、誰かのフルネームは、彼らの最初と最後の名前の連結です。 もし person
オブジェクトがあり、そのオブジェクトのユーザがフルネーム、ファーストネーム、ラストネームを設定でき、その変更が他の値にすぐに反映されるようにしたい場合、従来は
person.setLastName('Smith');person.setFirstName('Jimmy');person.getFullName(); // Jimmy Smith
という関数で構築していました。しかしこれは醜く、オブジェクトのユーザはプロパティが関連しているか気にする必要があり、もっと複雑な例では名前の場合ほど明白ではないかもしれません。 幸運にも、ECMAScript 5 で追加されたより良い方法があります。
ゲッターとセッターを紹介します。 ファーストネーム、ラストネーム、またはフルネームを設定し、他の2つを自動的に更新できるようにしたいと思います。 それらに続くのは、それらが関連するプロパティ (fullName
) と、プロパティにアクセス (name = person.fullName
) または修正 (person.fullName = 'Some Name'
) されたときの動作を定義する関数本体です。
これら 2 つのキーワードは、fullName
プロパティのゲッターとセッターというアクセッサ関数を定義します。 プロパティにアクセスすると、ゲッターからの戻り値が使用される。 値が設定されると、セッターが呼ばれ、設定された値が渡されます。 その値をどうするかはあなた次第ですが、セッターから返されるのは渡された値です – ですから、何も返す必要はありません。
公式の方法です。 Object.defineProperty
Getter と Setter を宣言するインラインの方法と同様に、Object.defineProperty
(MDN Documentation) を使用してより明示的に行うことができます。 このメソッドは 3 つの引数を取ります。 1つ目はプロパティを追加するオブジェクト、2つ目はプロパティの名前、3つ目はプロパティを説明するオブジェクト(プロパティの記述子として知られています)です。 以下は、上記の例を再現した例です。
var person = { firstName: 'Jimmy', lastName: 'Smith'};Object.defineProperty(person, 'fullName', {get: function() {return firstName + ' ' + lastName;},set: function(name) {var words = name.split(' ');this.firstName = words || '';this.lastName = words || '';}});
ここでの利点はすぐには明らかではありません。 最初のオブジェクトを作成した後にプロパティを追加できること以外に、実際の利点はありますか。
この方法でプロパティを定義すると、セッターまたはゲッターを定義するだけでなく、多くのことを行うことができます。
-
configurable
(デフォルトではfalse
): これが true の場合、プロパティの設定は将来変更可能になります。 -
enumerable
(デフォルトではfalse
): true の場合、オブジェクトをループするときにプロパティが表示されます (for (var key in obj)
)。
明示的なゲッターやセッターを持たないプロパティも定義できます。
Object.defineProperty(person, 'age', { value: 42});
これは person.age
を作成し、それを値 42 に設定します。 このプロパティは書き込み可能でないことに注意することが重要です。 person.age = 99
を呼び出しても何の効果もありません。 このようにして、読み取り専用のプロパティを作成することができます。 プロパティにvalue
キーが設定されている場合、ゲッターやセッターを持つことはできません。 プロパティは値またはアクセサを持つことができますが、両方を持つことはできません。
それだけでなく、enumerable
プロパティのデフォルトは false
なので、オブジェクトのキー上をループしても、このプロパティは表示されません。
プロパティを書き込み可能にしたい場合、writable
プロパティを設定する必要があります。
Object.defineProperty(person, 'age', { value: 42, writable: true});
これで、person.age = 99;
が望ましい効果を発揮します。 ゲッターとセッターにはその使用ケースがありますが、やり過ぎないようにしてください。 慎重に使用すれば、非常に強力です。 しかし、大きな力には大きな責任が伴います。
IE9 以降では、Safari 5+、Firefox 4+、Chrome 5+、および Opera 12+ とともに、Object.defineProperty
が完全にサポートされています。 Node.js を使用している場合は、完全なサポートがあります。 Node が大好きでしょう!
この記事は Tom Ashworth との共著です。 この記事をまとめるのに協力してくれた Tom に感謝します。
If you enjoyed this post, join the newsletter to get updates on new content 😎.
All blog posts
If you enjoyed this post, be sure to follow me on Twitter.
Thanks for all blog postsIf you enjoyed the post, continue to follow me on Twitter.
All the blog posts.