私の場合:
callback instanceof Function
または
typeof callback == "function"
それも重要ですか、違いは何ですか?
追加リソース:
JavaScript-Garden typeof vs 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
最後の1つは少し注意が必要です。
typeof null; // object
どちらも型情報を返すため、機能は似ていますが、個人的にはinstanceof
を好みます。文字列ではなく実際の型を比較するからです。型比較は人為的エラーが発生しにくく、文字列全体を比較するのではなくメモリ内のポインタを比較するため、技術的に高速です。
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()
メソッド(ECMAScript 2015)または__proto__
プロパティ(古いブラウザー、非推奨)によって明示的に設定することもできます。ただし、パフォーマンスの問題があるため、オブジェクトのプロトタイプを変更することはお勧めしません。したがって、instanceofはオブジェクトにのみ適用できます。ほとんどの場合、コンストラクターを使用して文字列または数値を作成することはありません。あなたはできる。しかし、あなたはほとんどしません。
また、instanceofは、オブジェクトの作成に使用されたコンストラクターを正確にチェックすることはできませんが、オブジェクトがチェック対象のクラスから派生した場合でもtrueを返します。ほとんどの場合、これは望ましい動作ですが、時々そうではありません。だから、その心を保つ必要があります。
別の問題は、スコープごとに実行環境が異なることです。これは、異なるビルトイン(異なるグローバルオブジェクト、異なるコンストラクタなど)があることを意味します。これにより、予期しない結果が生じる場合があります。
たとえば、[] instanceof window.frames[0].Array
と配列は前者を継承するため、Array.prototype !== window.frames[0].Array
はfalse
を返します。
また、プロトタイプがないため、未定義の値には使用できません。
次に、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"
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
だから、私はこれから両方を使用します。
instanceof
は、callback
がFunction
のサブタイプでも機能します。
その他の重要な実際の違い:
// 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
Javascriptのinstanceof
は不安定な場合があります-主要なフレームワークはその使用を避けようとしています。異なるウィンドウは、それが壊れる可能性のある方法の1つです。クラス階層もそれを混乱させる可能性があると思います。
オブジェクトが特定の組み込み型であるかどうかをテストするためのより良い方法があります(通常はこれが必要です)。ユーティリティ関数を作成して使用します。
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.Push);
}
等々。
プロトタイプのcallback.isFunction()
を使用することをお勧めします。
彼らは違いを理解し、その理由を当てにすることができます。
他のJSフレームワークにもそのようなものがあると思います。
instanceOf
は、他のウィンドウで定義された関数では機能しません。それらの機能はwindow.Function
とは異なります。
関数をチェックするときは、常に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
を使用して関数をチェックしてはならない理由です。
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
は、両方が適用される状況で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
重要な実際の違い:
var str = 'hello Word';
str instanceof String // false
typeof str === 'string' // true
理由を聞かないでください。
これは、ここにある他のすべての説明を補足する知識にすぎません-私は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)
Firefox 59.0b10(64ビット、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)
Firefox 59.0b10(64ビット、Windows)
注:関数がリストされている順序は、画像間で切り替わります!
クラスの名前を変更すると、コンパイラエラーが発生するため、instanceofを使用します。
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"
厳格なOO育成から来る
callback instanceof Function
文字列は、ひどいつづりや他のタイプミスの傾向があります。さらに、読みやすいと感じています。
もう1つのケースは、instanceof
とのみ照合できることです。trueまたはfalseを返します。 typeof
を使用すると、提供されたタイプを取得できます 何か
instanceofはtypeofより少し速いかもしれませんが、そのような可能性のある魔法のために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
パフォーマンスを念頭に置いて、一般的なハードウェアでtypeofを使用することをお勧めします。1000万回の繰り返しのループでスクリプトを作成する場合、命令:typeof str == 'string'は9ミリ秒かかり、 'string' instanceof Stringは19ミリ秒かかります