MENU

JavaScript構文オブジェクト

【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コンストラクターを使用できまるようになっています。

 

FunctionコンストラクターとObjectコンストラクター

 

ここで[[プロトタイプ]]は、プロトタイプチェーンを構成する、オブジェクトの内部要素です。
オブジェクトにプロパティが存在しない場合、[[プロトタイプ]]の参照先が検索されます。

 

prototypeプロパティは、"prototype"という名前のプロパティです。
オブジェクト中のprototypeプロパティは、プロトタイプチェーンの要素ではありません。

 

ただしFunctionコンストラクターの場合、[[プロトタイプ]]の参照先がprototypeプロパティになっているため、prototypeプロパティがプロトタイプチェーンに組み込まれています。
そのため、Function.prototype.apply() メソッドを、プロトタイプチェーンを辿ることで、Functionapply() として実行することができます。

 

また、prototypeプロパティの中に[[プロトタイプ]]が入れ子になっていて、prototypeプロパティ内に検索中のプロパティが見つからない場合、[[プロトタイプ]]の参照先が検索されます。
この[[プロトタイプ]]は、Object.prototype への参照です。
そのため、Function.toString() のように、Object.prototypeの関数も使用できます。

 

Functionと関数定義の関係

 

次に、関数定義から作成された関数オブジェクトについて考えてみます。
先ほども書いたように関数オブジェクトは、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 のとき、

 

  1. constructor のprototypeプロパティを cons とする
  2. object の[[プロトタイプ]]を objProto とする
  3. cons と objProto が一致するなら、true を返し演算終了
  4. objProto 内の[[プロトタイプ]] を objProto とする。なければ、 false を返し演算終了
  5. 3へ

 

 

 

 

 

 

 

参考記事:
【JavaScript】 プロトタイプとは?prototypeプロパティはプロトタイプではない件について

まとめ

instanceof演算子は、オブジェクトのプロトタイプと、コンストラクター関数のprototypeプロパティを比較しています。

 

長々と解説していますが、これだけわかっていれば十分です。

記事の内容について

 

こんにちはけーちゃんです。
説明するのって難しいですね。


「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

そんなときは、ご意見もらえたら嬉しいです。

ご意見はこちら。
https://affi-sapo-sv.com/info.php

【お願い】

お願い

■このページのURL


■このページのタイトル


■リンクタグ