# JavaScript 基礎編8(学習日:9/16,23)(クラス、例外処理) ## 1. クラス ### クラスとは 動作や状態を定義した構造のこと。 クラスに関する構文(class構文)はES2015以降登場した。それ以前は関数を用いていた。 ### クラスの定義 * classクラス名{}でクラスを定義する。 クラスにはコンストラクタ(インスタンスの初期化を行う)の記述が必要である。 ```javascript= class Class1{ constructor(){ } } ``` * クラス式でクラスを定義する。 ```javascript= const Class2 = class Class2{ constructor(){ } } ``` ### クラスとインスタンス new演算子を用いて、新しいインスタンスを作成できる。 クラスは通常の関数としては呼び出せない。 また、コンストラクタでreturnは通常書かない。 ```javascript= const om = class OsakaMetro{ constructor(midosuji,chuo){ this.midosuji = midosuji; this.chuo = chuo; } } const count = new om(10,5); console.log(count.midosuji); console.log(count.chuo); ``` ### プロトタイプメソッドとインスタンスメソッド プロトタイプメソッドは、class構文内に書かれたメソッドで、インスタンス間で共有される。 一方で、特殊なプロトタイプメソッドであるコンストラクタ内に書かれたメソッドは、通常のインスタンスメソッドの扱いとなる。 両者には次の違いがある。 * インスタンスからのメソッドの参照先が異なる。 * プロトタイプメソッド→インスタンス内で共有(同一のもの) * インスタンスメソッド→コンストラクタ毎に新たに作成 * Arrow Functionの利用可否 * プロトタイプメソッド→× * インスタンスメソッド→○(thisが静的に決まる) ```javascript= class Counter { constructor() { this.count = 0; this.increment = () => { this.count++; };//インスタンスメソッド } increment2(){ this.count++; }//プロトタイプメソッド } const counterA = new Counter(); const counterB = new Counter(); // 各インスタンスオブジェクトのメソッドの参照先は異なる console.log(counterA.increment !== counterB.increment); // => true // 各インスタンスオブジェクトのメソッドは共有されている(同じ関数を参照している) console.log(counterA.increment2 === counterB.increment2); // => true ``` ※プロトタイプメソッドとインスタンスメソッドが同一名の場合、インスタンスメソッドの呼び出しが優先される。互いに上書きはされない。(プロトタイプオブジェクトとプロトタイプチェーンの項を参照) ### アクセッサプロパティ(Getter,Setter) クラスには、値を取得するメソッド(Getter)と、値を更新するメソッド(Setter)が定義できる。 このプロパティは、他のプロパティと連動する動作も実現できる(array.length機能など) ```javascript= class Cars{ constructor(series){ this._series = series; } get midosuji(){ return this.series; } set midosuji(newSeries){ this.series = newSeries } } ``` ### 静的メソッド(Static) Class内のメソッド名の前にStaticをつけることで、インスタンス化しないクラスメソッドを作成できる。 インスタンスとしてメソッドを呼び出すことはできない。この場合のthisはクラス自身を指す。 ```javascript= class Cars{ constructor(series){ this._series = series; } static nagatsuru(){ return 70; }//Staticメソッド get midosuji(){ return this.series; } set midosuji(newSeries){ this.series = newSeries } } ``` ### プロトタイプオブジェクトとプロトタイプチェーン * プロトタイプオブジェクト class構文やコンストラクタは、プロトタイプオブジェクトのプロパティとして定義されている。(プロトタイプオブジェクトについては、基礎編3を参照) コンストラクタはクラス自身を参照する。 プロトタイプオブジェクトは、インスタンスオブジェクトとは別に定義されているため、両者が上書きされることはない。 * プロトタイプチェーン プロトタイプメソッドの呼び出しは、次の2つの工程に分かれる。  * インスタンス作成時に、プロトタイプオブジェクトの参照を保存する。  インスタンス作成時には、クラスのプロトタイプオブジェクトの参照が保存される仕組みとなっている。直接アクセスは不可だが、Object.getPrototypeOfメソッドで参照可能である。  * インスタンスからプロパティを参照する際、内部プロパティまで参照する。  プロパティ参照は、インスタンス内にプロパティが無い場合、前項で保存した内部的なプロトタイプオブジェクトまで参照する。(そこにもなければundefined) この仕組みをプロトタイプチェーンという。 ### 継承 classクラス名の後ろに、extends親クラス名を入力することで、子クラスを定義できる。 親クラスで定義されたコンストラクタを子クラスで利用するにはsuperを用いる。(コンストラクタで何も処理しない場合は省略可) また、コンストラクタの処理順は親クラス(Superの呼び出し)→子クラスの順番となる。(子クラスで親クラスの内容を使いたい時は順番を間違えないように) ### プロトタイプチェーンと継承 プロトタイプチェーンの仕組みを利用すると、親クラスのプロトタイプオブジェクトや静的オブジェクトも子クラスで参照可能となる。これをプロトタイプ継承という。 子クラスのプロトタイプメソッドから親クラスのプロトタイプオブジェクトを呼び出すには、super.プロパティ名で参照可能である。 あるクラスが指定したクラスをプロトタイプ継承しているか判定するには、instanceof演算子で判定できる。 ArrayやString等のビルドインオブジェクトも参照可能である。 ```javascript= class Parent { method() { console.log("Parent#method"); } } class Child extends Parent { method() { console.log("Child#method"); // `this.method()`だと自分(`this`)のmethodを呼び出して無限ループする // そのため明示的に`super.method()`とParent#methodを呼び出す super.method(); } } const child = new Child(); child.method(); // コンソールには次のように出力される // "Child#method" // "Parent#method" ``` ## 2. 例外処理 ### 例外処理とは プログラムに予期せぬ処理が発生した場合した際の処理を記述するものである。 代表的な表し方として以下のものがある。 ### try…catch構文 tryブロック内の処理に対し、例外が発生した場合の処理をcatchブロック内に記述する。例外の有無にかかわらず行う処理はfinallyブロック内に記述する。 catchかfinallyのどちらか一方は記述する必要がある。 ```javascript= try{ divided () }catch{ console.log("関数'divided'は定義されていません") }finally{ console.log("処理が完了しました"); } ```` ### throw文 ユーザが意図的に例外を投げる時に用いる。 throw new Error(エラーメッセージ)で例外処理を定義できる。 ### エラーオブジェクト エラーメッセージはエラーオブジェクトに格納される。エラーオブジェクトを呼び出し、エラーメッセージを確認するには、catch文をcatch(error)と記述することで、errorからエラーメッセージを呼び出せる。 ```javascript= try{ divided () }catch(error){ console.log(error);//=>ReferenceError: divided is not defined }finally{ console.log("処理が完了しました"); } ```` ### ビルドインエラー エラーメッセージで表示される分類別のエラーは、ビルドインエラーとして定義されている。各エラーは以下の時に表示される。 * ReferenceError 存在しない変数・関数を参照している。 * SyntaxError 構文が不正である。実行前に発生するため、Try…Catchできない。 * TypeError 型が不正である。 ビルドインエラーのインスタンスを作成し、インスタンスを例外に投げることも可能である。 ### エラーとスタックトレース スタックトレースとは、エラーの種類とエラーの発生位置を教えてくれる機能である。 console.errorでスタックトレースをコンソール出力できる。 デバッグを行う際に非常に役立つ。 ###### tags: `JavaScript`