お知らせ:2021/2/18 ツールサイト(affi-sapo-sv.com)から、開発ノートを独立させました。
【JavaScript】 instanceof演算子とは?何を比較しているのか?
更新日:2020/10/22
ツイートJavaScriptにはinstanceof演算子というものがある。
使用する機会が非常に限られるため、あまり知られていない演算子である。
また、知っていても何を行っているかわからないという人も多いだろう。
そこで今回は、instanceof演算子について解説してみようと思う。
instanceof演算子とは
instanceofは、オブジェクトがコンストラクター関数のインスタンスかどうかを判定する演算子です。
instanceofの構文
object instanceof constructor
objectは、確認したいオブジェクト。
constructorは、コンストラクター関数です。
コンストラクター関数については、次の記事を参照してください。
■【JavaScript】 コンストラクターとは?関数とは違うのか?
instanceofの使用例
function a(){} const b = new a(); console.log( b instanceof a ); // true console.log( b instanceof Object ); // true console.log( b instanceof b ); // Uncaught TypeError: b is not a function
上の例は、コンストラクター関数aからインスタンスbを作成しています。
その後、bに対して、instanceofで判定をおこなっています。
最初の判定は、bがaより作成されているので、trueです。
2番目の判定は、bがObjectコンストラクター関数のインスタンスかどうか判定しています。
結果はtrueです。
これは、function文により内部的に作成されるFunctionコンストラクター関数が、Objectコンストラクター関数のインスタンスであること。
よって、Functionコンストラクター関数から作成されるインスタンスは、Objectコンストラクター関数のインスタンスでもあります。
3番目の判定は、bがb自身のインスタンスかどうか判定しています。
結果はfalseです。
instanceof演算子の比較対象
instanceof演算子は、オブジェクトのプロトタイプと、コンストラクター関数のprototypeプロパティを比較しています。
解説が非常に難しいですが、できるだけ簡単に解説してみます。
JavaScriptの関数は、Functionコンストラクターのインスタンスです。
FunctionとObjectの関係
ですが、インスタンスの前に、まずはFunctionコンストラクターについて解説します。
Functionコンストラクターは、次のようにObjectコンストラクターprototypeプロパティを自分自身に取り込むことで、Objectコンストラクターを使用できまるようになっています。
ここで[[プロトタイプ]]は、プロトタイプチェーンを構成する、オブジェクトの内部要素です。
オブジェクトにプロパティが存在しない場合、[[プロトタイプ]]の参照先が検索されます。
prototypeプロパティは、"prototype"という名前のプロパティです。
オブジェクト中のprototypeプロパティは、プロトタイプチェーンの要素ではありません。
ただしFunctionコンストラクターの場合、[[プロトタイプ]]の参照先がprototypeプロパティになっているため、prototypeプロパティがプロトタイプチェーンに組み込まれています。
そのため、Function.prototype.apply() メソッドを、プロトタイプチェーンを辿ることで、Functionapply() として実行することができます。
また、prototypeプロパティの中に[[プロトタイプ]]が入れ子になっていて、prototypeプロパティ内に検索中のプロパティが見つからない場合、[[プロトタイプ]]の参照先が検索されます。
この[[プロトタイプ]]は、Object.prototype への参照です。
そのため、Function.toString() のように、Object.prototypeの関数も使用できます。
Functionと関数定義の関係
次に、関数定義から作成された関数オブジェクトについて考えてみます。
先ほども書いたように関数オブジェクトは、Functionコンストラクターのインスタンスです。
そのため、次のような図式が成り立ちます。
ここで作成された関数aの[[プロトタイプ]]は、Function.prototypeへの参照です。
そのため、FunctionとObjectの機能を使用することができます。
関数aのprototypeプロパティには、初期値としてObjectコンストラクターのインスタンスがセットされます。
そのため、Object.prototypeへの参照が含まれています。
次に、プログラムコードで指定したメソッド等が、セットされます。
しかし、Functionコンストラクターとは異なり、関数aのprototypeプロパティはプロトタイプチェーンに組み込まれていません。
そのため、a.f1() のように、プロトタイプチェーン経由でprototype内のメソッドを実行することができません。
関数定義とインスタンスの関係
Functionコンストラクターのインスタンスは、コンストラクター関数でもあります。
次は、コンストラクター関数である関数aから、インスタンスを作成してみます。
コンストラクター関数aのインスタンスであるオブジェクトbは、コンストラクター内でthisオブジェクトにセットしたプロパティを持っています。
その他に[[プロトタイプ]]として、関数aのprototypeプロパティへの参照を持っています。
インスタンスはprototypeプロパティでつながっている
ここまでの解説からわかるように、最終的なインスタンスは[[プロトタイプ]]を辿ることで、元となるオブジェクトの機能を使用することができます。
ただし、[[プロトタイプ]]の参照先は、各オブジェクトのprototypeプロパティです。
このことから、instanceof演算子は、次のような処理をおこなっています。
object instanceof constructor のとき、
- constructor のprototypeプロパティを cons とする
- object の[[プロトタイプ]]を objProto とする
- cons と objProto が一致するなら、true を返し演算終了
- objProto 内の[[プロトタイプ]] を objProto とする。なければ、 false を返し演算終了
- 3へ
まとめ
instanceof演算子は、オブジェクトのプロトタイプと、コンストラクター関数のprototypeプロパティを比較しています。
長々と解説していますが、これだけわかっていれば十分です。
記事の内容について

説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
ご意見はこちら。
https://note.affi-sapo-sv.com/info.php
【お願い】

■このページのURL
■このページのタイトル
■リンクタグ