【JavaScriptクイズ】第4問:いつでも最新の値を取得できるプロパティの作り方
JavaScriptの文法や便利な使い方について、気軽なクイズ形式で解説する記事を書いていきます。
今回のテーマは「プロパティの取得」です。では、さっそく問題です!
問題
三角形を扱うJavaScriptのプログラムを作りました。「底辺の長さ」と「高さ」から、「面積」を計算するというものです。
"use strict";
class Triangle {
constructor(base, height) {
this.base = base;
this.height = height;
this.updateArea();
}
updateArea() {
this.area = this.base * this.height / 2.0;
}
}
// 「底辺の長さ」が6、「高さ」が4の三角形の「面積」は?
let t = new Triangle(6, 4);
console.log(`三角形の面積は${t.area}です。`);
// 「底辺の長さ」を7にすると、「面積」はいくつになる?
t.base = 7;
t.updateArea();
console.log(`三角形の面積は${t.area}になりました。`);
三角形の面積は12です。
三角形の面積は14になりました。
クラスTriangle
には、3つのプロパティがあります。
-
base
:底辺の長さ -
height
:高さ -
area
:面積
area
は、関数updateArea
を実行するとbase
とheight
から計算されます。そのため、プログラム中には次のような行があるのですが……
t.updateArea();
この1行を書かないと、area
を最新の値に更新できないところが不満です。いつでも最新のarea
の値を取得できるようにするには、どうすればいいか分かりますか?
ヒントを見る?
area
の値が、常にbase
とheight
から計算されるようにするには?
答えを見る?
「ゲッター(getter)」を使えば、プログラムは次のように書けます。
"use strict";
class Triangle {
constructor(base, height) {
this.base = base;
this.height = height;
}
get area() {
return this.base * this.height / 2.0;
}
}
// 「底辺の長さ」が6、「高さ」が4の三角形の「面積」は?
let t = new Triangle(6, 4);
console.log(`三角形の面積は${t.area}です。`);
// 「底辺の長さ」を7にすると、「面積」はいくつになる?
t.base = 7;
console.log(`三角形の面積は${t.area}になりました。`);
解説
問題のプログラムでは、「面積」の計算結果をいったんarea
に格納して覚えておき、あとで取得できるようにしていました。
class Triangle {
constructor(base, height) {
this.base = base;
this.height = height;
this.updateArea();
}
updateArea() {
this.area = this.base * this.height / 2.0; // 計算結果をareaに格納
}
}
いつでも最新の「面積」を得られるようにするには、値を取得するときに計算するのがいいでしょう。順を追って、やり方を説明します。
ステップ1:最新の値を関数で取得する
まずは、「面積」を計算して返す関数を作りましょう。具体的には、次のようにします。
class Triangle {
constructor(base, height) {
this.base = base;
this.height = height;
}
getArea() { // 関数なら、いつでも最新の計算結果を返せる
return this.base * this.height / 2.0;
}
}
updateArea
を廃止して、代わりにgetArea
を作りました。この関数は、計算結果を覚えておくのではなく、その場で返すという動作をします。
これにより、プログラムの後半は次のように変わります。
// 「底辺の長さ」が6、「高さ」が4の三角形の「面積」は?
let t = new Triangle(6, 4);
console.log(`三角形の面積は${t.getArea()}です。`);
// 「底辺の長さ」を7にすると、「面積」はいくつになる?
t.base = 7;
console.log(`三角形の面積は${t.getArea()}になりました。`);
目論見どおり、updateArea
を呼び出していた1行をなくすことができました。
でも、t.area
とプロパティを取得するだけで済んでいた部分を、t.getArea()
と関数呼び出しに置き換える必要がありました。これは、やりたかったこととは違うので、もう一工夫必要です。
ステップ2:値をプロパティとして取得する
JavaScriptには、プロパティを関数に結び付ける「ゲッター」という仕組みがあります。これを使えば、関数の戻り値をプロパティとして取得することが可能です。
具体的には、get
というキーワードを使って、次のように書きます。
class Triangle {
constructor(base, height) {
this.base = base;
this.height = height;
}
get area() { // この関数の戻り値はプロパティのように取得できる
return this.base * this.height / 2.0;
}
}
これにより、プログラムの後半部分は次のようになります。
// 「底辺の長さ」が6、「高さ」が4の三角形の「面積」は?
let t = new Triangle(6, 4);
console.log(`三角形の面積は${t.area}です。`);
// 「底辺の長さ」を7にすると、「面積」はいくつになる?
t.base = 7;
console.log(`三角形の面積は${t.area}になりました。`);
以上で、プロパティt.area
による「面積」の取得方法を変更することなく、updateArea
の呼び出しを削除できました!
まとめ
JavaScriptでは、「ゲッター(getter)」を使うとプロパティの取得を関数に結び付けられます。もしかすると、「ゲッターがあるのなら、セッターもあるのでは?」と思った人もいるかもしれませんね。そのとおりです!プロパティへの書き込みも、「セッター(setter)」を使って関数に結び付けることが可能です。
とはいえゲッターとセッターは、あまり使いすぎるとプログラムが複雑になってしまうかもしれません。メリットを感じられるときにだけ使うのがおすすめです。
「ほかのプロパティによって値が決まるプロパティ」を作りたいときは、ゲッターを使うメリットがあるでしょう。今回のプログラムは、
- 「底辺の長さ」と「高さ」によって、「面積」が決まる
というものでした。ほかには……
- 「速さ」と「時間」によって、「距離」が決まる
- 「赤(Red)」と「緑(Green)」と「青(Blue)」によって、「カラーコード(RGB値)」が決まる
などの場合にも、うまく活用すればプログラムをスッキリ書けるのではないかと思います。
なお、下記のページには、今回とよく似た「三角形の面積」を題材にしたC言語のクイズがあります。よろしければ、チェックしてみてください。
また、下記の本では「素数の探索」を題材に、JavaScriptとC言語を含む10種類のプログラミング言語を紹介しています。
Discussion