340

JavaScriptのinstanceofキーワードは、JavaScriptはオブジェクト指向プログラミング言語ではないと人々が考える傾向があるため、最初に遭遇したときは非常に混乱する可能性があります。

  • それは何ですか?
  • それはどのような問題を解決しますか?
  • それが適切なのはいつですか、そうでないのはいつですか?
4

11 に答える 11

303

instanceof

左側(LHS)オペランドは、クラスの実際のコンストラクターである右側(RHS)オペランドに対してテストされる実際のオブジェクトです。基本的な定義は次のとおりです。

現在のオブジェクトをチェックし、オブジェクトが指定されたオブジェクトタイプである場合はtrueを返します。

ここにいくつかの良い例があります、そしてこれはMozillaの開発者サイトから直接取られた例です:

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)

言及する価値のあることの1つはinstanceof、オブジェクトがクラスのプロトタイプから継承する場合にtrueと評価されることです。

var p = new Person("Jon");
p instanceof Person

から継承するので、それp instanceof Personは本当です。pPerson.prototype

OPの要求に応じて

サンプルコードと説明を含む小さな例を追加しました。

変数を宣言するときは、特定の型を指定します。

例えば:

int i;
float f;
Customer c;

上記は、いくつかの変数、つまり、、、およびを示してifますc。タイプは、、integerおよびfloatユーザー定義のCustomerデータ型です。上記のようなタイプは、JavaScriptだけでなく、任意の言語に対応できます。ただし、JavaScriptでは、変数を宣言するときに型を明示的に定義しないとvar x、xは数値/文字列/ユーザー定義のデータ型になる可能性があります。それで、instanceofそれはオブジェクトをチェックして、それが指定されたタイプであるかどうかを確認するので、上からCustomerオブジェクトを取得して、次のことができます。

var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!

上記ではc、タイプがで宣言されていることを確認しましたCustomer。私たちはそれを新しくし、それがタイプであるかどうかをチェックしましたCustomer。確かに、それはtrueを返します。次に、Customerオブジェクトを引き続き使用して、それがであるかどうかを確認しますString。いいえ、オブジェクトではなくオブジェクトStringを新しくしたことは間違いありません。この場合、falseを返します。CustomerString

本当に簡単です!

于 2010-03-15T17:52:03.837 に答える
97

これまでのコメントではカバーされていないように見えるinstanceofの重要な側面があります。それは継承です。instanceofを使用して評価されている変数は、プロトタイプの継承により、複数の「タイプ」に対してtrueを返す可能性があります。

たとえば、タイプとサブタイプを定義しましょう。

function Foo(){ //a Foo constructor
    //assign some props
    return this;
}

function SubFoo(){ //a SubFoo constructor
    Foo.call( this ); //inherit static props
    //assign some new props
    return this;
}

SubFoo.prototype = Object.create(Foo.prototype); // Inherit prototype
SubFoo.prototype.constructor = SubFoo;

いくつかの「クラス」ができたので、いくつかのインスタンスを作成し、それらが何のインスタンスであるかを調べます。

var 
    foo = new Foo()
,   subfoo = new SubFoo()
;

alert( 
    "Q: Is foo an instance of Foo? "
+   "A: " + ( foo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is foo an instance of SubFoo? " 
+   "A: " + ( foo instanceof SubFoo ) 
); // -> false

alert( 
    "Q: Is subfoo an instance of Foo? "
+   "A: " + ( subfoo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of SubFoo? "
+   "A: " + ( subfoo instanceof SubFoo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of Object? "
+   "A: " + ( subfoo instanceof Object ) 
); // -> true

その最後の行を見ますか?関数へのすべての「新しい」呼び出しは、Objectから継承するオブジェクトを返します。これは、オブジェクト作成の省略形を使用する場合にも当てはまります。

alert( 
    "Q: Is {} an instance of Object? "
+   "A: " + ( {} instanceof Object ) 
); // -> true

そして、「クラス」定義自体はどうですか?それらは何のインスタンスですか?

alert( 
    "Q: Is Foo an instance of Object? "
+   "A:" + ( Foo instanceof Object) 
); // -> true

alert( 
    "Q: Is Foo an instance of Function? "
+   "A:" + ( Foo instanceof Function) 
); // -> true

を使用することで、たとえば、オブジェクトと関数を区別できると(誤って)想定しているため、任意のオブジェクトがMULTIPLE型のインスタンスになる可能性があることを理解することが重要だと思いますinstanceof。この最後の例は、関数オブジェクトであることを明確に示しています。

これは、継承パターンを使用していて、ダックタイピング以外の方法でオブジェクトの子孫を確認したい場合にも重要です。

誰もが探索するのに役立つことを願っていますinstanceof

于 2011-06-30T15:56:59.130 に答える
89

ここでの他の答えは正しいですが、instanceof実際にどのように機能するかについては触れていません。これは、そこにいる一部の言語弁護士にとって興味深いかもしれません。

JavaScriptのすべてのオブジェクトにはプロトタイプがあり、__proto__プロパティからアクセスできます。関数には、関数によって作成されたオブジェクトprototypeの初期値であるプロパティもあります。__proto__関数が作成されると、その関数には。の一意のオブジェクトが与えられますprototype。オペレーターはこのinstanceof一意性を使用して回答を提供します。instanceof関数として記述した場合、次のようになります。

function instance_of(V, F) {
  var O = F.prototype;
  V = V.__proto__;
  while (true) {
    if (V === null)
      return false;
    if (O === V)
      return true;
    V = V.__proto__;
  }
}

これは基本的に、ECMA-262エディション5.1(ES5とも呼ばれます)のセクション15.3.5.3を言い換えています。

任意のオブジェクトを関数のプロパティに再割り当てでき、オブジェクトの構築後にprototypeオブジェクトのプロパティを再割り当てできることに注意してください。__proto__これにより、いくつかの興味深い結果が得られます。

function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();

f instanceof F;   // returns true
f instanceof G;   // returns true
g instanceof F;   // returns true
g instanceof G;   // returns true

F.prototype = {};
f instanceof F;   // returns false
g.__proto__ = {};
g instanceof G;   // returns false
于 2012-02-09T23:04:33.257 に答える
46

instanceofは、オブジェクトを宣言するときに「new」キーワードを使用して定義されていることに注意してください。JonHの例では;

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

彼が言及しなかったのはこれです。

var color1 = String("green");
color1 instanceof String; // returns false

「new」を指定すると、Stringコンストラクター関数の終了状態が、単に戻り値に設定されるのではなく、実際にcolor1変数にコピーされます。これは、新しいキーワードが何をするかをよりよく示していると思います。

function Test(name){
    this.test = function(){
        return 'This will only work through the "new" keyword.';
    }
    return name;
}

var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.

var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'

「new」を使用すると、関数内の「this」の値が宣言された変数に割り当てられますが、使用しない場合は、代わりに戻り値が割り当てられます。

于 2011-04-10T21:54:28.717 に答える
8

そして、次のように、エラー処理とデバッグに使用できます。

try{
    somefunction();
} 
catch(error){
    if (error instanceof TypeError) {
        // Handle type Error
    } else if (error instanceof ReferenceError) {
        // Handle ReferenceError
    } else {
        // Handle all other error types
    }
}
于 2011-05-22T02:47:52.533 に答える
5

それは何ですか?

Javascriptはプロトタイプ言語であり、「継承」のプロトタイプを使用することを意味します。演算子はinstanceof、コンストラクター関数のprototypepropertypeが__proto__オブジェクトのチェーンに存在するかどうかをテストします。これは、次のことを行うことを意味します(testObjが関数オブジェクトであると仮定)。

obj instanceof testObj;
  1. オブジェクトのプロトタイプがコンストラクターのプロトタイプと等しいかどうかを確認します。obj.__proto__ === testObj.prototype >>これがtrue instanceof返される場合はtrue
  2. プロトタイプチェーンを登ります。例:obj.__proto__.__proto__ === testObj.prototype >>これがの場合は。true instanceofを返しtrueます。
  3. オブジェクトの完全なプロトタイプが検査されるまで、ステップ2を繰り返します。オブジェクトのプロトタイプチェーンのどこにも一致しないtestObj.prototype場合、instanceof演算子はを返しfalseます。

例:

function Person(name) {
  this.name = name;
}
var me = new Person('Willem');

console.log(me instanceof Person); // true
// because:  me.__proto__ === Person.prototype  // evaluates true

console.log(me instanceof Object); // true
// because:  me.__proto__.__proto__ === Object.prototype  // evaluates true

console.log(me instanceof Array);  // false
// because: Array is nowhere on the prototype chain

それはどのような問題を解決しますか?

オブジェクトが特定のプロトタイプから派生しているかどうかを簡単にチェックするという問題を解決しました。たとえば、関数がさまざまなプロトタイプを持つことができるオブジェクトを受信する場合。次に、プロトタイプチェーンのメソッドを使用する前に、instanceof演算子を使用して、これらのメソッドがオブジェクト上にあるかどうかを確認できます。

例:

function Person1 (name) {
  this.name = name;
}

function Person2 (name) {
  this.name = name;
}

Person1.prototype.talkP1 = function () {
  console.log('Person 1 talking');
}

Person2.prototype.talkP2 = function () {
  console.log('Person 2 talking');
}


function talk (person) {
  if (person instanceof Person1) {
    person.talkP1();
  }
  
  if (person instanceof Person2) {
    person.talkP2();
  }
  
  
}

const pers1 = new Person1 ('p1');
const pers2 = new Person2 ('p2');

talk(pers1);
talk(pers2);

ここでは、talk()最初に関数でプロトタイプがオブジェクトにあるかどうかがチェックされます。この後、実行する適切なメソッドが選択されます。このチェックを行わないと、存在しないメソッドが実行され、参照エラーが発生する可能性があります。

それが適切なのはいつですか、そうでないのはいつですか?

私たちはすでにこれを乗り越えました。オブジェクトで何かをする前に、オブジェクトのプロトタイプをチェックする必要がある場合に使用します。

于 2018-09-05T07:43:33.603 に答える
3
//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
    this.numWheels = numWheels;
}

//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);
于 2010-03-15T18:08:35.003 に答える
1

「いつ適切なのか、いつ適切でないのか」という質問に対して、私の2セント:

instanceof本番コードではめったに役立ちませんが、コードが正しいタイプのオブジェクトを返す/作成することを表明したいテストでは役立ちます。コードが返す/作成するオブジェクトの種類を明示することで、コードを理解して文書化するためのツールとして、テストがより強力になります。

于 2013-07-24T02:01:49.063 に答える
0

私は実際のアプリケーションを見つけたばかりで、これからもっと頻繁に使用するようになると思います。

jQueryイベントを使用する場合、直接(イベントなしで)呼び出すこともできる、より一般的な関数を作成したい場合があります。instanceof関数の最初のパラメーターがのインスタンスであるかどうかを確認し、jQuery.Event適切に反応するために使用できます。

var myFunction = function (el) {                
    if (el instanceof $.Event) 
        // event specific code
    else
        // generic code
};

$('button').click(recalc);    // Will execute event specific code
recalc('myParameter');  // Will execute generic code

私の場合、関数はすべて(ボタンのクリックイベントを介して)または1つの特定の要素のみに対して何かを計算する必要がありました。私が使用したコード:

var recalc = function (el) { 
    el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el);
    // calculate...
};
于 2013-07-26T12:18:16.933 に答える
0

instanceofのための単なる構文糖ですisPrototypeOf

function Ctor() {}
var o = new Ctor();

o instanceof Ctor; // true
Ctor.prototype.isPrototypeOf(o); // true

o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent

instanceofオブジェクトのコンストラクターのプロトタイプに依存するだけです。

コンストラクターは単なる通常の関数です。厳密に言えば、すべてがJavascriptのオブジェクトであるため、これは関数オブジェクトです。また、すべての関数にはプロトタイプがあるため、この関数オブジェクトにはプロトタイプがあります。

プロトタイプは単なる通常のオブジェクトであり、別のオブジェクトのプロトタイプチェーン内にあります。つまり、別のオブジェクトのプロトタイプチェーンに含まれていると、オブジェクトがプロトタイプになります。

function f() {} //  ordinary function
var o = {}, // ordinary object
 p;

f.prototype = o; // oops, o is a prototype now
p = new f(); // oops, f is a constructor now

o.isPrototypeOf(p); // true
p instanceof f; // true

instanceof演算子は、Javascriptには存在しないクラスを偽造するため、避ける必要があります。classES2015にもないキーワードにもかかわらず、これもclass単なる構文糖衣です...しかし、それは別の話です。

于 2016-07-26T20:55:13.337 に答える
0

@SebastianSimon私の最後の答えは8歳です(私がラメしたとき)そしてそれは私がいくつかのブル*ヒットを書いた可能性があります:)

簡単に言うと、現在、私が使用しているのはインスタンスを使用してinstanceofいる場合のみでclassあり、動作は受け取るクラスによって異なります。404がErrorA(リソースが存在しない)であるかErrorB(サービスが見つからない)であるかを区別したい-ライブラリの応答コードは混乱していましたが、運が良ければ、異なるエラークラスを使用してスローされました。

間違いなく(現在)プリミティブを反映する型をチェックするためにそれを使用することはありません'msg'-ライブラリが返されるかどうかはわかりませんnew String('msg')

プリミティブは内部的に文字列オブジェクトにラップされているため、どちらにもStringクラスに属するメソッドがあります。'msg'内部的には通訳によることを意味します。これらは両方ともStringsですが、instanceofここでは演算子が不十分であるようです-sthかどうかを確認します。typeofプリミティブまたはクラスです。 &&の組み合わせを使用しますinstanceofが、外部JSライブラリから返されたものにのみ使用します。

Currenlty TypeScriptはこの問題を解決しており、とでこのような悪意のあるチェックを使用する必要がなくなりましtypeofinstanceof

于 2021-03-17T23:37:52.793 に答える