私の特定のケースでは:
callback instanceof Function
また
typeof callback == "function"
違いは何ですか?
追加リソース:
JavaScript-Garden typeofとinstanceof
私の特定のケースでは:
callback instanceof Function
また
typeof callback == "function"
違いは何ですか?
追加リソース:
JavaScript-Garden typeofとinstanceof
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
最後のものは少しトリッキーです:
typeof null; // object
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"
したがって、私の意見では、チェックしている可能性のあるデータのタイプによって異なります。
物事を明確にするために、次の 2 つの事実を知っておく必要があります。
Object.setPrototypeOf()
__proto__
したがって、instanceof はオブジェクトにのみ適用されます。ほとんどの場合、コンストラクターを使用して文字列や数値を作成することはありません。あなたはできる。しかし、あなたはほとんどそうしません。
また、 instanceof は、オブジェクトの作成に使用されたコンストラクターを正確に確認することはできませんが、オブジェクトがチェックされているクラスから派生している場合でも、true を返します。ほとんどの場合、これは望ましい動作ですが、そうでない場合もあります。ですから、その心を保つ必要があります。
もう 1 つの問題は、スコープごとに実行環境が異なることです。これは、それらが異なる組み込み (異なるグローバル オブジェクト、異なるコンストラクターなど) を持っていることを意味します。これにより、予期しない結果が生じる場合があります。
たとえば、[] instanceof window.frames[0].Array
は を返します。false
これArray.prototype !== window.frames[0].Array
は、配列が前者から継承されているためです。
また、プロトタイプがないため、未定義の値には使用できません。
ここで、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 以降、独自の typeof == "symbol"を持つ Symbol と呼ばれる型がもう 1 つあります。
console.log(typeof Symbol());
// expected output: "symbol"
Safari5とInternetExplorer9で、非常に興味深い(「恐ろしい」と読まれる)動作を発見しました。これを使用して、ChromeとFirefoxで大成功を収めました。
if (typeof this === 'string') {
doStuffWith(this);
}
次に、IE9でテストしましたが、まったく機能しません。ビッグサプライズ。しかし、Safariでは断続的です!だから私はデバッグを開始し、InternetExplorerが常にを返していることがわかりましたfalse
。しかし、最も奇妙なことは、SafariがJavaScript VMで何らかの最適化を行っているように見えることです。これはtrue
、初めてですが、false
リロードを押すたびに!
私の脳はほとんど爆発した。
だから今私はこれに落ち着きました:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
そして今、すべてがうまく機能しています。呼び出すことができ"a string".toString()
、文字列のコピーを返すだけであることに注意してください。
"a string".toString() === new String("a string").toString(); // true
なので、これからは両方使っていきます。
その他の重要な実用上の違い:
// 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
instanceof
callback
が のサブタイプの場合にも機能しFunction
ます。
instanceof
プリミティブでは機能しません。たとえば、"foo" instanceof String
が返されますがfalse
、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)
関数をチェックするときは、常に を使用する必要があります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
これが、関数をチェックするために決して使用してはならない理由です。
Performance
typeof
is faster than instanceof
in situations where both are applicable.
Depending on your engine, the performance difference in favor of typeof
could be around 20%. (Your mileage may vary)
Here is a benchmark testing for 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));
Result
instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
重要な実用上の違い:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
理由を聞かないでください。
もちろん大事に……!
例を挙げて説明しましょう。この例では、関数を 2 つの異なる方法で宣言します。
function declaration
と Function Constructorの両方を使用します。これら 2 つの異なるシナリオでどのようtypeof
に動作するかを確認します。instanceof
関数宣言を使用して関数を作成します。
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
このような異なる結果の考えられる説明は、関数宣言を行ったのでtypeof
、それが関数であることを理解できることですtypeof
。 typeof が操作される式であるかどうかをチェックするため、この場合はCall Methodが実装されているかどうか。それがメソッドを実装する場合、それは関数です。それ以外の場合はそうではありません。MyFunc
Call
関数コンストラクターを使用して関数を作成します。
var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used
typeof MyFunc2 == 'function' // true
MyFunc2 instanceof Function // true
ここでは、 が関数であると同時に演算子であるtypeof
と主張します。メソッドが実装されているかどうかを確認することは既にわかっています。のインスタンスになります。そのため、にも解決されます。MyFunc2
instanceof
typeof
MyFunc2
Call
MyFunc2
call
typeof
function constructor
MyFunc2
Function constructor
instanceof
true
より安全に使用できるものは何ですか?
両方のケースでわかるように、typeof
演算子はここで関数を扱っていることを正常にアサートできます。より安全ですinstanceof
。のインスタンスではないためinstanceof
、 の場合は失敗します。function declaration
function declarations
Function constructor
ベストプラクティス:
Gary Raffertyが示唆したように、最善の方法は typeof と instanceof の両方を一緒に使用することです。
function isFunction(functionItem) {
return typeof(functionItem) == 'function' || functionItem instanceof Function;
}
isFunction(MyFunc) // invoke it by passing our test function as parameter
パフォーマンスを念頭に置いて、通常のハードウェアで typeof を使用することをお勧めします。1,000 万回の反復のループを含むスクリプトを作成する場合、命令: typeof str == 'string' は 9 ミリ秒かかり、'string' instanceof String は 19 ミリ秒かかります。