オブジェクト構文

【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オブジェクトの関数コードで新しいオブジェクトにプロパティがセットされ、インスタンスとして返されます。

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

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

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

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

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

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

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

 

このサイトは、リンクフリーです。大歓迎です。