Part14:オブジェクトの作成

海未「オブジェクトについては、これまで何回か触れてきましたね」
穂乃果「オブジェクトリテラルとか、Arrayオブジェクトとかやったよね」
海未「・・・奇跡的に穂乃果が覚えているようなので、これまで説明した部分は軽く流すことにして、より複雑なオブジェクトの定義に焦点を当てていきましょう」


オブジェクト初期化子

海未「これまでに見てきたオブジェクトリテラルによる記法はオブジェクト初期化子と呼ばれていて、以下のようなものですが目新しいものではないでしょう」

音ノ木坂学院の高坂穂乃果です!

ことり「プロパティ名と値のペアなんだよね」
穂乃果「あれ、オブジェクトに関数って入れられるの?」
海未「そういえば関数については説明していませんでしたね。関数を変数に代入できたのと同じように、プロパティとして設定することもできます。プロパティとしての関数はメソッドと呼びます」
ことり「書き方はわかるけど・・・thisってなんだろう」
海未「原則的には、それが属するオブジェクト、この例ならhonokaを指していると考えてください」
穂乃果「原則的には・・・?」
海未「違うものを指す場合があるのです。例えば」

honoka:undefined
umi:undefined
kotori:undefined

海未「高階関数を書いたと考えてください。これは適当にforEachを使っていますが、forEachが引数に取る関数内ではthisはhonokaではありません」
ことり「ほんとだ、this.schoolがundefinedになってる・・・」
海未「これを解決する方法として」

海未「var self = this;という黒魔術がよく使われます。決してスマートな書き方ではありませんが」
ことり「関数の外側の変数は見えるから、forEachに渡す関数内ではselfを見ればいいんだね」
海未「これをもっときれいに解決する方法があります。アロー関数を思い出してください」
穂乃果「えーっと・・・無名関数を短く書けるやつ」
海未「それです。書き方が簡略化できる以外に、このthisの扱いにおいて便利なのがアロー関数です」

海未「同じ処理をアロー関数で書き直しました。この場合、ちゃんとthis.schoolで意図した値を参照できます」
ことり「これ間違えると、間違えに気付くまでが大変そうだね・・・」
海未「thisの参照先はJavaScriptの闇のひとつだと思っています」


コンストラクタ関数

海未「さて、honokaオブジェクトを例に説明してきましたが、ことりや私のオブジェクトも作れないと不公平・・・いえ、作る必要が出てきたとしましょう」
ことり「海未ちゃん、目立ちたいなら遠慮しなくていいんだよ。いつも鏡の前でやってるみたいに♪」
海未「ことり!その話はそこまでです!」

海未「・・・とにかく、kotoriオブジェクトやumiオブジェクトを作るのにいちいちオブジェクト初期化子を使うのは大変です。そこで、コンストラクタ関数を使うと楽になります」

音ノ木坂学院の高坂穂乃果です!
音ノ木坂学院の南ことりです!

海未「Idolというコンストラクタ関数を用意しています。これが雛形になって、個人個人のオブジェクトが作られるというわけです」
ことり「newしてるところ、DateとかMapとかと同じだね」
海未「そうですね。newを使って、インスタンスと呼ばれる具体的なアイドル1人1人のオブジェクトを生成しています」
穂乃果「Idol("高坂穂乃果", 16, "音ノ木坂学院")ってしてるところは、そのコンストラクタ関数を普通に呼び出してるだけ?」
海未「そうです。Idol関数に引数を与えて実行しているだけなので、そこは特別な挙動はありません」
ことり「じゃあ、Idol関数の中は・・・このthisはさっきと同じ?」
海未「新しく作られるオブジェクトそのもの、honokaやkotoriを指していると考えてください」
ことり「ふんふん、自分自身のプロパティを設定していくんだね」
海未「コンストラクタ関数は一般的なオブジェクト指向言語におけるクラスに相当します。しかしクラスベース言語の考え方をそのまま持ち込むと痛い目に遭うので気を付けてください」

海未「ところで、オブジェクトのプロパティに別のオブジェクトを設定することもできます」

海未「この例では、穂乃果はμ’sに所属しています。honoka.group.nameでμ’sを得ることができます」
ことり「これは大丈夫かな」


Object.create

海未「Object.createを使ってオブジェクトを作ることができます」

音ノ木坂学院の高坂穂乃果です!
音ノ木坂学院の南ことりです!

海未「コンストラクタ関数版と見比べるとやっていることは大差がないのですが、値の設定の部分が少し複雑になっていますね」
穂乃果「なんでこんなことに?」
海未「各プロパティに書き込みができるか、列挙可能か、など、細かい制御ができるのがObject.createの特徴です」
穂乃果「難しい分、多機能なんだ」
海未「newを使うかObject.createを使うか、といったあたり宗教対立みたいなものがあるようですから、どちらを使うか私見は控えておきます」


getter/setter

海未「getterとsetterは、値の取得や設定を行うメソッドです。getsetというプレフィックス付きでメソッドを定義します」

高坂穂乃果、音ノ木坂学院
南ことり、音ノ木坂学院

ことり「うーん、普通のメソッドと何が違うんだろう・・・」
海未「getterやsetterは仮想的なプロパティとして振る舞うと考えてください。honoka.indroductionのようにプロパティのように呼び出せますが、実際にはそれに対応する値がどこかにあるわけではありません」
ことり「毎回計算して返してるんだよね」
海未「はい。そして実体がないということは、getterには値を設定することはできません。読み取り専用のプロパティになりますね」
穂乃果「ってことは、setterはその逆、と・・・」
海未「はい。値を設定はできますが読み出すことはできません。この場合は、同名のgetterとsetterがあるので外からは読み書き可能に見えますが」
穂乃果「どういうときに使うの?」
海未「値の設定時や読み出し時に何か処理を挟みたいとき、内部データに直接アクセスしてほしくない場合でしょうか。後者はこの書き方ではだめで、クロージャと組み合わせる必要がありますが」


海未「さて、全てを説明したわけではありませんが、基本的なオブジェクトの作り方については一通り分かったと思います」
穂乃果「やりかたがいろいろあって迷っちゃうよ~」
海未「歴史的な経緯から、このあたりは色々な事情があるのです」
ことり「でも、思ったほど難しくなかった気がするな」
海未「・・・本当の地獄はこれからです」
ことり「え・・・」
海未「穂乃果は、天国と地獄、どちらから体験したいですか?」
穂乃果「え、ええっと・・・天国だけじゃダメ?」
海未「駄目です。・・・次回までに覚悟を決めてきてください」
穂乃果「ふえぇ~」


LINEで送る
Pocket


返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です