【JavaScript】 instanceof演算子とは?何を比較しているのか?
更新日:2020/10/22
JavaScriptにはinstanceof演算子というものがある。
使用する機会が非常に限られるため、あまり知られていない演算子である。
また、知っていても何を行っているかわからないという人も多いだろう。
そこで今回は、instanceof演算子について解説してみようと思う。
instanceof演算子とは
instanceofは、オブジェクトがコンストラクター関数のインスタンスかどうかを判定する演算子です。
コンストラクター関数は他言語のクラスに相当するので、”オブジェクトがクラスのインスタンスかどうかを判定する”と言った方がわかりやすいかもしれません。
instanceofの構文
instanceofの構文
object instanceof constructor
objectは、確認したいオブジェクト。
constructorは、コンストラクター関数です。
コンストラクター関数については、次のページを参照してください。
■【JavaScript】 コンストラクターとは?関数とは違うのか?
instanceofとコンストラクター関数
次のように二つのコンストラクター関数を用意して、一方からインスタンスを生成してみます。
instanceofの使用例
function a(){}
function b(){}
const c = new a();
console.log( c instanceof a ); // true
console.log( c instanceof b ); // false
インスタンスcと生成元であるaにinstanceofを適用するとtrueを返します。
一方、関連性のないcとinstanceof演算をおこなうとfalseになります。
instanceofとClass構文
Class構文での動作も確認してみます。
class a{}
class b{}
const c = new a();
console.log( c instanceof a ); // true
console.log( c instanceof b ); // false
そもそもコンストラクター関数定義とClass定義で生成されるものはほぼ同じです。
そのため結果も同じになります。
JavaScriptのクラスについては、次のページを読んでみてください。
■【JavaScript】 JSにおけるクラスとは?正体についても調べてみた
instanceofとClass構文での継承
Class構文のextendsで継承したクラスも、instanceof演算子はtrueを返します。
class a{}
class b extends a{}
const c = new b();
console.log( c instanceof a ); // true
console.log( c instanceof b ); // true
つまり継承したクラスもインスタンスとして認識されます。
instanceof演算子の比較対象
instanceof演算子は、オブジェクトのプロトタイプと、コンストラクター関数のprototypeプロパティを比較しています。
解説が非常に難しいですが、できるだけ簡単に解説してみます。
JavaScriptのインスタンスとは
まずはインスタンスを作成するnew演算子が何をやっているかを理解する必要があります。
そもそもコンストラクター関数やクラスの実体は、functionオブジェクトです。
functionオブジェクトは、実行されるコード本体の他に多数のプロパティを持っています。
そのうちの一つにprototypeというプロパティがあります。
functionオブジェクト{
[[ECMAScriptCode]] : 関数コード
[[Prototype]] : プロトタイプチェーン
・・・・その他多数のプロパティprototype:{
プロパティ: ・・・・
プロパティ: ・・・・
}
}
functionオブジェクトをnew演算子で実行すると、新しいオブジェクトが作成されます。
このときfunctionオブジェクトのprototypeプロパティが、新しいオブジェクトのプロトタイプチェーンに組み込まれます。
新しいオブジェクト{
[[Prototype]] : functionオブジェクトのprototypeプロパティへの参照
}
その後functionオブジェクトの関数コードで新しいオブジェクトにプロパティがセットされ、インスタンスとして返されます。
次の記事も参照してみてください。
■【JavaScript】 プロトタイプとは?prototypeプロパティはプロトタイプではない件について
■【JavaScript】 new演算子は何をやっている?
■【JavaScript】 new したら コンストラクタではないと言われたなぜ?
extendsされたインスタンス
Class構文でextendsを使用した場合のインスタンスについても解説しておきます。
extendsで継承指定されたオブジェクトは、プロトタイプの2階層目に組み込まれます。
次のようなclass構文があるとします。
class b extends a{}
このクラスのインスタンスには、次のようなプロトタイプが構成されます。
新しいオブジェクト{
[[Prototype]] : b.prototypeプロパティへの参照{
プロパティ: ・・・・
プロパティ: ・・・・
[[Prototype]] : a.prototypeプロパティへの参照{
プロパティ: ・・・・
プロパティ: ・・・・
}
}
}
instanceof演算子の動作
上の解説からわかるとおり、JavaScriptでのインスタンスとは、あるオブジェクトのprototypeプロパティをプロトタイプチェーンに組み込んだオブジェクトを指します。
そのため次のinstanceof演算子は、
a instanceof b
内部で次のような判定をおこなっています。
aのプロトタイプチェーン === bのprototypeプロパティ
ただし一致しない場合は、下層のプロトタイプチェーンがチェックされます。
例えば次のようにextendsされているとします。
class b extends c{};
a instanceof c
bのprototypeプロパティと比較します。
aのプロトタイプチェーン === bのprototypeプロパティ → false
結果がfalseなので、下層がチェックされます。
aのプロトタイプチェーン === cのprototypeプロパティ → true
一致するので、trueが演算結果となります。
Object.getPrototypeOfとinstanceof演算子
Object.getPrototypeOf()を使用すると、instanceof演算子と同様の確認ができます。
ただしこちらは、階層を意識する必要があります。
class a{}
class b extends a{}
const c = new b();
// インスタンスcのプロトタイプチェーンとb.prototypeが一致
console.log( Object.getPrototypeOf(c) === b.prototype ); // true
// インスタンスcのプロトタイプチェーン2階層目とa.prototypeが一致
console.log( Object.getPrototypeOf(Object.getPrototypeOf(c)) === a.prototype ); // true
まとめ
instanceof演算子は、オブジェクトのプロトタイプと、コンストラクター関数のprototypeプロパティを比較しています。
長々と解説していますが、これだけわかっていれば十分です。
更新日:2020/10/22
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。