吉本集の個人ブログ
Web制作の技術について書いています。たまに日記も書きます。

【JS入門】コンストラクタ関数について

2018年1月18日 / category : javascript

今回はコンストラクタ関数について解説したいと思います。JavaScript言語には定義済みのオブジェクトがたくさんあります。これについては違う記事で触れる機会があればと思いますが、自分でオブジェクトを作る方法に関しては、以前の記事で解説しました。この記事とは違うオブジェクトを生成する方法として、コンストラクタ関数があります。

コンストラクタ関数とは

コンストラクタ関数でオブジェクトを生成することができます。コンストラクタ関数で生成されたオブジェクトをインスタンスと呼びます。まずは次のコードを見てみましょう。

sample.js
function obj(){
	this.name = '吉本';
}
let a = new obj();
console.log( a.name ); // '吉本'

関数objがコンストラクタ関数になるのですが、これだけではわからないので順に解説していきますが、上のコードでこれまで解説してきていない2つのキーワードが出てきました。thisとnewです。thisについて解説するとこれはこれで長くなります。ここでは簡単に触れる程度にしておきます。thisは関数内で使用される特殊なキーワードで、関数が実行された際にその関数が属しているオブジェクトを指します。まずは次のコードを見てみます。

sample.js
function test(){
	console.log(this); // Window {...}
}
test();

関数testを実行すると、Window{…}と表示されました。thisはその関数が属しているオブジェクトを指すと先ほど解説しました、この結果を見ると、関数testが属しているオブジェクトは、Windowオブジェクトになるということになります。関数testはトップレベルで実行しています。以前の記事でもトップレベルという表現を何度かしてきましたが、Webブラウザ上のトップレベルは、Windowオブジェクトになるということになります。Windowオブジェクトについても触れておきたいところですが、それは次回以降の記事で解説することにします。トップレベルに定義した関数testを実行すると、関数test内で参照するthisはWindowオブジェクトを指すという確認ができました。
それでは次のコードではどうでしょうか。

sample.js
function test(){
	console.log(this); // test {...}
}
let obj = new test();

関数testに変更はありませんが、thisが指すオブジェクトが変わってしまいました。本来ここでなぜか・・・というところを深く掘っていきたいところですが、今回の記事はthisについてではありませんので、簡単に解説します。コンストラクタ関数を実行すると、その関数の中でthisが新しく生成されます。次のようなイメージなります。
これはあくまでイメージです、実際には次のコードを記述するとエラーになります。

sample.js
function test(){
	let this = {};
	console.log(this);
	return this;
}
let obj = new test();

さらにこのthisはtestオブジェクトのプロパティを継承しています。コンソールで指しているthisがこれにあたるため、先ほどのthisと結果が変わっています。続いて、new演算子とインスタンスの解説をします。

new演算子

new演算子とはインスタンスを生成する演算子です。構文は次のようになります。

new 関数名(引数)

new演算子をつけて関数を実行すると、インスタンスとなって返ってきます。

sample.js
function test(){};
let obj = new test();
console.log(obj); // test {}

上のコードの場合、変数objにtestオブジェクトのインスタンスが代入され、変数objはインスタンスとなりました。ただし、コンソールでは、testオブジェクトを表示しています。変数objがインスタンスかどうかを確認するために、instanceof演算子を使用します。

instanceof演算子

object instanceof コンストラクタ関数

上の構文で確認することができます。もし、objectが指定したコンストラクタ関数のインスタンスであれば、trueが返ってきます。
それでは先ほどのコードで確かめてみます。

sample.js
function test(){};
let obj = new test();
console.log( obj instanceof test); // true

期待通りtrueが返ってきましたので、変数objがtestオブジェクトのインスタンスであると確認できました。
では、このインスタンスというのはどういうオブジェクトでしょうか。

インスタンスとは

インスタンスとはどういうオブジェクトなのか確認してみたいと思います。コンストラクタ関数をnew演算子をつけて実行することで、コンストラクタ関数の持っているプロパティを継承し、新しいオブジェクトを生成します。この生成されたオブジェクトがインスタンスですがコンストラクタ関数のプロパティが継承されているという点が重要です。さらに、コンストラクタ関数とは別のオブジェクトであるという点も重要です。
それでは最初に記述したコードを改めて確認します。

sample.js
function obj(){
	this.name = '吉本';
}
let a = new obj();
console.log( a.name ); // '吉本'

改めて解説すると、変数aはobjオブジェクトのインスタンスです。objオブジェクトのインスタンスなので、このインスタンスはobjオブジェクトのプロパティを継承しています。また、objオブジェクトとインスタンスは別のオブジェクトですので、次の比較はfalseを返します。

sample.js
function obj(){
	this.name = '吉本';
}
let a = new obj();
console.log( obj === a ); // false

続いて、objオブジェクトのインスタンスを複数生成してみます。

sample.js
function obj(){
	this.name = '吉本';
}
let a = new obj();
let b = new obj();
console.log( a === b ); // false

変数aと変数bにそれぞれtestオブジェクトのインスタンスを生成し比較してみましたが、こちらもfalseになりました。同じtestオブジェクトのインスタンスですが、別々のオブジェクトということが確認できました。さらに確認してみます。

sample.js
function obj(){
	this.name = '吉本';
}
let a = new obj();
let b = new obj();
a.name = 'よしもと';
b.name = 'ヨシモト';
console.log( a.name ); // 'よしもと'
console.log( b.name ); // 'ヨシモト'

この結果は想像できたかもしれませんが、testオブジェクトのプロパティを継承した別のオブジェクトですので、プロパティの値も互いを干渉することなく、保持することができます。以上が、インスタンスについての解説ですが、JavaScript言語は、オブジェクトの理解が非常に重要です。次回は、オブジェクトについてもう少し深く解説をしたいと思います。