web-dev-qa-db-ja.com

typeofとinstanceofの違いは何ですか?一方を使用する場合と他方を使用する場合

私の場合:

callback instanceof Function

または

typeof callback == "function"

それも重要ですか、違いは何ですか?

追加リソース:

JavaScript-Garden typeof vs instanceof

343
farinspace

カスタムタイプにはinstanceofを使用します。

var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false 

単純な組み込み型にはtypeofを使用します。

'example string' instanceof String; // false
typeof 'example string' == 'string'; // true

'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false

true instanceof Boolean; // false
typeof true == 'boolean'; // true

99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true

function() {} instanceof Function; // true
typeof function() {} == 'function'; // true

複雑な組み込み型にはinstanceofを使用します。

/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object

[] instanceof Array; // true
typeof []; //object

{} instanceof Object; // true
typeof {}; // object

最後の1つは少し注意が必要です。

typeof null; // object
473

どちらも型情報を返すため、機能は似ていますが、個人的にはinstanceofを好みます。文字列ではなく実際の型を比較す​​るからです。型比較は人為的エラーが発生しにくく、文字列全体を比較するのではなくメモリ内のポインタを比較するため、技術的に高速です。

120
Soviut

Typeofを使用する正当な理由は、変数が未定義である可能性がある場合です。

alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception

Instanceofを使用する正当な理由は、変数がnullである可能性がある場合です。

var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar  instanceof Object); // alerts "false"

だから本当に私の意見では、それはあなたがチェックしている可能性のあるデータのタイプに依存するだろう。

94
Kenneth J

物事を明確にするには、2つの事実を知る必要があります。

  1. instanceof演算子は、constructorprototype propertyがオブジェクトのプロトタイプチェーン。ほとんどの場合、これは、このコンストラクターまたはその子孫を使用してオブジェクトがcreatedされたことを意味します。ただし、プロトタイプはObject.setPrototypeOf()メソッド(ECMAScript 2015)または__proto__プロパティ(古いブラウザー、非推奨)によって明示的に設定することもできます。ただし、パフォーマンスの問題があるため、オブジェクトのプロトタイプを変更することはお勧めしません。

したがって、instanceofはオブジェクトにのみ適用できます。ほとんどの場合、コンストラクターを使用して文字列または数値を作成することはありません。あなたはできる。しかし、あなたはほとんどしません。

また、instanceofは、オブジェクトの作成に使用されたコンストラクターを正確にチェックすることはできませんが、オブジェクトがチェック対象のクラスから派生した場合でもtrueを返します。ほとんどの場合、これは望ましい動作ですが、時々そうではありません。だから、その心を保つ必要があります。

別の問題は、スコープごとに実行環境が異なることです。これは、異なるビルトイン(異なるグローバルオブジェクト、異なるコンストラクタなど)があることを意味します。これにより、予期しない結果が生じる場合があります。

たとえば、[] instanceof window.frames[0].Arrayと配列は前者を継承するため、Array.prototype !== window.frames[0].Arrayfalseを返します。
また、プロトタイプがないため、未定義の値には使用できません。

  1. typeof演算子は、値が6つの基本型のいずれかに属するかどうかをテストします: "number」、「string」、「boolean」、「object "、"function "または"undefined "。文字列「オブジェクト」がすべてのオブジェクトに属している場合(関数はオブジェクトですが、typeof演算子に独自の値があります)、「null」値と配列(「null」の場合はバグですが、このバグは非常に古いです) 、それが標準になっています)。コンストラクターに依存せず、値が未定義の場合でも使用できます。しかし、オブジェクトに関する詳細は提供しません。必要な場合は、instanceofに進みます。

次に、1つの注意が必要なことについて話しましょう。コンストラクターを使用してプリミティブ型を作成するとどうなりますか?

let num = new Number(5);
console.log(num instanceof Number); // print true
console.log(typeof num); // print object
num++; //num is object right now but still can be handled as number
//and after that:
console.log(num instanceof Number); // print false
console.log(typeof num); // print number

魔法のようです。そうではありません。それは、いわゆるボックス化(オブジェクトでプリミティブ値をラップ)とボックス化解除(オブジェクトからラップされたプリミティブ値を抽出)です。そのような種類のコードは「少し」壊れやすいようです。もちろん、コンストラクタを使用してプリミティブ型を作成することは避けられます。しかし、ボクシングがあなたを襲うかもしれないとき、別の可能な状況があります。プリミティブ型でFunction.call()またはFunction.apply()を使用する場合。

function test(){
  console.log(typeof this);
} 
test.apply(5);

これを回避するには、厳格モードを使用できます。

function test(){
  'use strict';
  console.log(typeof this);
} 
test.apply(5);

upd:ECMAScript 2015以降、Symbolと呼ばれるもう1つの型があり、独自のtypeof == "symbol"があります。

console.log(typeof Symbol());
// expected output: "symbol"

MDNでそれについて読むことができます:( Symboltypeof )。

26

Safari 5とInternet Explorer 9で非常に興味深い(「恐ろしい」と呼ばれる)動作を発見しました。これを使用してChromeとFirefoxで大成功を収めました。

if (typeof this === 'string') {
    doStuffWith(this);
}

その後、IE9でテストしましたが、まったく機能しません。ビッグサプライズ。しかし、Safariでは断続的です!デバッグを開始すると、Internet Explorerがalwaysfalseを返します。しかし、最も奇妙なことは、SafariがJavaScript VMで何らかの最適化を行っているように見えることです。 true the firsttime、but falseリロードするたびに!

私の脳はほとんど爆発しました。

だから今、私はこれで解決しました:

if (this instanceof String || typeof this === 'string')
    doStuffWith(this.toString());
}

そして今、すべてがうまく機能します。 "a string".toString()を呼び出すことができ、文字列のコピー、つまり.

"a string".toString() === new String("a string").toString(); // true

だから、私はこれから両方を使用します。

14
Justin Force

instanceofは、callbackFunctionのサブタイプでも機能します。

7
newacct

その他の重要な実際の違い:

// Boolean

var str3 = true ;

alert(str3);

alert(str3 instanceof Boolean);  // false: expect true  

alert(typeof str3 == "boolean" ); // true

// Number

var str4 = 100 ;

alert(str4);

alert(str4 instanceof Number);  // false: expect true   

alert(typeof str4 == "number" ); // true
7

Javascriptのinstanceofは不安定な場合があります-主要なフレームワークはその使用を避けようとしています。異なるウィンドウは、それが壊れる可能性のある方法の1つです。クラス階層もそれを混乱させる可能性があると思います。

オブジェクトが特定の組み込み型であるかどうかをテストするためのより良い方法があります(通常はこれが必要です)。ユーティリティ関数を作成して使用します。

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.Push);
}

等々。

4
levik

プロトタイプのcallback.isFunction()を使用することをお勧めします。

彼らは違いを理解し、その理由を当てにすることができます。

他のJSフレームワークにもそのようなものがあると思います。

instanceOfは、他のウィンドウで定義された関数では機能しません。それらの機能はwindow.Functionとは異なります。

3
alamar

関数をチェックするときは、常にtypeofを使用する必要があります。

違いは次のとおりです。

var f = Object.create(Function);

console.log(f instanceof Function); //=> true
console.log(typeof f === 'function'); //=> false

f(); // throws TypeError: f is not a function

これが、instanceofを使用して関数をチェックしてはならない理由です。

3
vitaly-t

instanceofはプリミティブでは機能しません。たとえば、"foo" instanceof Stringfalseを返しますが、typeof "foo" == "string"trueを返します。

一方、typeofは、カスタムオブジェクト(またはクラス、呼び出したいもの)に関しては、おそらくあなたが望むことをしません。例えば:

function Dog() {}
var obj = new Dog;
typeof obj == 'Dog' // false, typeof obj is actually "object"
obj instanceof Dog  // true, what we want in this case

関数が「関数」プリミティブと「関数」のインスタンスの両方であることがありますが、他のプリミティブ型のように機能しないため、少し奇妙です.

(typeof function(){} == 'function') == (function(){} instanceof Function)

しかし

(typeof 'foo' == 'string') != ('foo' instanceof String)
3
Omnimike

パフォーマンス

typeofは、両方が適用される状況でinstanceofよりも高速です。

エンジンによっては、typeofを優先するパフォーマンスの違いは20%前後になる可能性があります。 (マイレージは異なる場合があります

Arrayのベンチマークテストは次のとおりです。

var subject = new Array();
var iterations = 10000000;

var goBenchmark = function(callback, iterations) {
    var start = Date.now();
    for (i=0; i < iterations; i++) { var foo = callback(); }
    var end = Date.now();
    var seconds = parseFloat((end-start)/1000).toFixed(2);
    console.log(callback.name+" took: "+ seconds +" seconds.");
    return seconds;
}

// Testing instanceof
var iot = goBenchmark(function instanceofTest(){
     (subject instanceof Array);
}, iterations);

// Testing typeof
var tot = goBenchmark(function typeofTest(){
     (typeof subject == "object");
}, iterations);

var r = new Array(iot,tot).sort();
console.log("Performance ratio is: "+ parseFloat(r[1]/r[0]).toFixed(3));

結果

instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
2
Martin Peter

重要な実際の違い:

var str = 'hello Word';

str instanceof String   // false

typeof str === 'string' // true

理由を聞かないでください。

2
Barney

これは、ここにある他のすべての説明を補足する知識にすぎません-私はnotどこでも.constructorを使用することを提案しています。

TL; DR:typeofがオプションではない状況で、あなたが知っているときプロトタイプチェーンを気にしないObject.prototype.constructor は、instanceofよりも実行可能な、またはさらに優れた代替となります。

x instanceof Y
x.constructor === Y

1.1から標準になっているため、後方互換性について心配する必要はありません。

ムハンマド・ウーマーは、ここのどこかのコメントでこれについて簡潔に言及しました。プロトタイプを使用してすべてで動作します-したがって、nullまたはundefinedではないすべてのもの:

// (null).constructor;      // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties

(1).constructor;                 // function Number
''.constructor;                  // function String
([]).constructor;                // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor;               // function Boolean()
true.constructor;                // function Boolean()

(Symbol('foo')).constructor;     // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor

Array.prototype === window.frames.Array;               // false
Array.constructor === window.frames.Array.constructor; // true

さらに、ユースケースによっては、instanceofよりもa lot速くなります(おそらく、プロトタイプチェーン全体をチェックする必要がないためです)。私の場合、値が型付き配列であるかどうかをすばやく確認する方法が必要でした。

function isTypedArrayConstructor(obj) {
  switch (obj && obj.constructor){
    case Uint8Array:
    case Float32Array:
    case Uint16Array:
    case Uint32Array:
    case Int32Array:
    case Float64Array:
    case Int8Array:
    case Uint8ClampedArray:
    case Int16Array:
      return true;
    default:
      return false;
  }
}

function isTypedArrayInstanceOf(obj) {
  return obj instanceof Uint8Array ||
    obj instanceof Float32Array ||
    obj instanceof Uint16Array ||
    obj instanceof Uint32Array ||
    obj instanceof Int32Array ||
    obj instanceof Float64Array ||
    obj instanceof Int8Array ||
    obj instanceof Uint8ClampedArray ||
    obj instanceof Int16Array;
}

https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812

そして結果:

Chrome 64.0.3282.167(64ビット、Windows)

Typed Array instanceof vs constructor - 1.5x faster in Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10(64ビット、Windows)

Typed Array instanceof vs constructor - 30x faster in Firefox 59.0b10 (64-bit, Windows)

好奇心から、typeofに対して簡単なおもちゃのベンチマークを行いました。驚くべきことに、パフォーマンスはそれほど悪くなく、Chromeでは少し高速に見えます。

let s = 0,
    n = 0;

function typeofSwitch(t) {
    switch (typeof t) {
        case "string":
            return ++s;
        case "number":
            return ++n;
        default:
            return 0;
    }
}

// note: no test for null or undefined here
function constructorSwitch(t) {
    switch (t.constructor) {
        case String:
            return ++s;
        case Number:
            return ++n;
        default:
            return 0;
    }
}

let vals = [];
for (let i = 0; i < 1000000; i++) {
    vals.Push(Math.random() <= 0.5 ? 0 : 'A');
}

https://run.perf.zone/view/typeof-vs-constructor-string-or-number-151914262357

注:関数がリストされている順序は、画像間で切り替わります!

Chrome 64.0.3282.167(64ビット、Windows)

String/Number typeof vs constructor - 1.26x faster in Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10(64ビット、Windows)

注:関数がリストされている順序は、画像間で切り替わります!

String/Number typeof vs constructor - 0.78x slower in Firefox 59.0b10 (64-bit, Windows)

2
Job

クラスの名前を変更すると、コンパイラエラーが発生するため、instanceofを使用します。

1
Robert
var newObj =  new Object;//instance of Object
var newProp = "I'm xgqfrms!" //define property
var newFunc = function(name){//define function 
        var hello ="hello, "+ name +"!";
        return hello;
}
newObj.info = newProp;// add property
newObj.func = newFunc;// add function

console.log(newObj.info);// call function
// I'm xgqfrms!
console.log(newObj.func("ET"));// call function
// hello, ET!

console.log(newObj instanceof Object);
//true
console.log(typeof(newObj));
//"object"
1
xgqfrms

厳格なOO育成から来る

callback instanceof Function

文字列は、ひどいつづりや他のタイプミスの傾向があります。さらに、読みやすいと感じています。

0
Keplerf1

もう1つのケースは、instanceofとのみ照合できることです。trueまたはfalseを返します。 typeofを使用すると、提供されたタイプを取得できます 何か

0

instanceoftypeofより少し速いかもしれませんが、そのような可能性のある魔​​法のために2番目の方が好きです:

function Class() {};
Class.prototype = Function;

var funcWannaBe = new Class;

console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function
0
Suprido

パフォーマンスを念頭に置いて、一般的なハードウェアでtypeofを使用することをお勧めします。1000万回の繰り返しのループでスクリプトを作成する場合、命令:typeof str == 'string'は9ミリ秒かかり、 'string' instanceof Stringは19ミリ秒かかります

0
Khalid Rafik