私の特定のケースでは:
callback instanceof Function
または
typeof callback == "function"
それも重要ですか、違いは何ですか?
追加リソース:
JavaScript-Garden typeofとinstanceof
Object.prototype.toString ecma-international.org/ecma-262/6.0/…
.constructor代わりにプロパティを。
私の特定のケースでは:
callback instanceof Function
または
typeof callback == "function"
それも重要ですか、違いは何ですか?
追加リソース:
JavaScript-Garden typeofとinstanceof
Object.prototype.toString ecma-international.org/ecma-262/6.0/…
.constructor代わりにプロパティを。
回答:
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
Use instanceof for complex built in types-これはまだエラーが発生しやすいです。ES5 Array.isArray()らを使用する方が良い。または推奨シム。
どちらも型情報を返すため、機能的には似ていますが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"
だから私の意見では、それはあなたがチェックしている可能性のあるデータのタイプに依存するでしょう。
instanceof、プリミティブ型と比較できないことに注意してください。typeofはできます。
undefined instanceof Objectはfalseを返し、例外をスローしません。その変化がどれほど最近かはわかりませんが、instanceofより魅力的になります。
undefined instanceof Objectええと、undefined定義されているので、例外をスローしません。定数は名前空間に存在します。変数が存在しない場合(たとえば、タイプミスのため)、instanceofは例外をスローします。一方、存在しない変数でtypeofを使用すると、「未定義」になります。
明確にするために、2つの事実を知る必要があります。
Object.setPrototypeOf()メソッド(ECMAScript 2015)または__proto__プロパティ(古いブラウザー、非推奨)によって明示的に設定することもできます。ただし、パフォーマンスの問題があるため、オブジェクトのプロトタイプを変更することはお勧めしません。 したがって、instanceofはオブジェクトにのみ適用できます。ほとんどの場合、文字列または数値を作成するためにコンストラクターを使用していません。あなたはできる。しかし、あなたはほとんどしません。
また、instanceofは、オブジェクトの作成に使用されたコンストラクタを正確にチェックできませんが、チェックされているクラスからオブジェクトが派生した場合でも、trueを返します。ほとんどの場合、これは望ましい動作ですが、そうでない場合もあります。したがって、そのことを覚えておく必要があります。
別の問題は、スコープによって実行環境が異なることです。これは、それらに異なる組み込み(異なるグローバルオブジェクト、異なるコンストラクターなど)があることを意味します。これにより、予期しない結果が生じる可能性があります。
例えば、[] 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);
これを回避するには、strictモードを使用できます。
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"
if an object is created by a given constructor これは誤りです。 o instanceof CoがC.prototypeから継承した場合、trueを返します。これについては後で回答の中で言及しましたが、あまり明確ではありません。
私はSafari 5とInternet Explorer 9でいくつかの非常に興味深い(「恐ろしい」と読む)動作を発見しました。これを使用してChromeとFirefoxで大成功を収めました。
if (typeof this === 'string') {
doStuffWith(this);
}
その後、IE9でテストしましたが、まったく動作しません。ビッグサプライズ。しかし、Safariでは断続的です。デバッグを開始したところ、Internet Explorerが常に戻ってきていることがわかりましたfalse。しかし、奇妙なことは、SafariはそれがそのJavaScriptのVMに最適化のいくつかの種類をやっているように見えるということである最初の時間が、毎回あなたはリロードをヒット!truefalse
私の脳はほとんど爆発しました。
だから今私はこれに落ち着きました:
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
instanceofJavaScriptは不安定な場合があります-主要なフレームワークはその使用を避けようとしていると思います。異なるウィンドウは、ウィンドウが壊れる可能性がある方法の1つです。クラス階層も混乱させる可能性があると思います。
オブジェクトが特定の組み込み型であるかどうかをテストするためのより良い方法があります(通常はこれが必要です)。ユーティリティ関数を作成して使用します。
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
等々。
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、関数のチェックに使用してはならない理由です。
typeofそれが間違っていると主張することができます- (オブジェクト)と(関数)のfすべてです。私を除いて、すべての関数はECMAScriptのオブジェクトであるため、それが関数であることを知っているので、それがオブジェクトであることもわかっているので、使用する方が理にかなっています。逆は真実ではありません- それから知っていることは確かに私はそれが関数でもあることを知りません。ObjectFunctioninstanceoftypeoffobject
length、nameおよびcall関数からの属性を取得しますが、それらはすべて無効です。さらに悪い何、それは呼び出すことはできませんし、TypeErrorそれは言います:f is not a function。
重要な実用的な違い:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
理由を聞かないで。
strは文字列プリミティブであり、文字列オブジェクトではないためです。同じことが数値プリミティブとブールプリミティブにも当てはまります。これらは、「構築された」対応物である文字列、数値、ブールオブジェクトのインスタンスではありません。JavaScriptは、必要に応じてこれらの3つのプリミティブをオブジェクトに自動的に変換します(オブジェクトのプロトタイプチェーンでメソッドを利用するなど)。実際の違いとは逆に、から、instanceofは配列のチェックに適していますtypeof [] == "object" // true。
パフォーマンス
typeofinstanceof両方が当てはまる状況よりも高速です。
エンジンによっては、20%typeof程度のパフォーマンスの差が生じる可能性があります。(走行距離は異なる場合があります)
以下がベンチマークテストです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
instanceof 常にオブジェクトのプロトタイプチェーンに従います。そのため、パフォーマンスのペナルティは、プロトタイプチェーンのどこまでクラスinstanceofがテストされるかによって異なります。したがって、継承チェーンが短い場合、ペナルティは低くなり(、[] instanceof Arrayなど{} instanceof Object)、長くなるほど大きくなります。したがって、仮想コードの観点から両方obj instanceof SomeClassとtypeof obj !== 'string'が同じことを意味する場合(複数のクラスを介してifではなく、でテストを行う場合switchなど)、パフォーマンスの観点から2番目を選択することをお勧めします。
これは、ここにある他のすべての説明を補足する知識です- どこでも使用することはお勧めしません.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。私の場合、値が型付き配列であるかどうかを確認する高速な方法が必要でした:
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-1519142623570
注:関数がリストされている順序で画像を切り替えます!
Chrome 64.0.3282.167(64ビット、Windows)
Firefox 59.0b10(64ビット、Windows)
注:関数がリストされている順序で画像を切り替えます!
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"
かかわらず、instanceofのは、その後、より速く少しかもしれtypeofを、私はので、そのような可能な魔法の二番目のを好みます。
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
もう1つのケースは、照合できるのinstanceofはtrueかfalse のみを返す場合です。ではtypeof、あなたは、提供の種類を取得することができます何かを
もちろん重要です........!
これについて例を挙げて説明します。この例では、関数を2つの異なる方法で宣言します。
function declarationとFunction Constructorの両方を 使用します。これら2つの異なるシナリオでの動作typeofとinstanceof動作について説明します。
関数宣言を使用して関数を作成します。
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
そのような異なる結果の考えられる説明は、関数宣言を行ったときにtypeof、それが関数であることを理解できることです。typeofこの場合、typeofが操作されている式、この場合はCallメソッドが実装されているかどうかをチェックするためです。それがメソッドを実装する場合、それは関数です。それ以外の場合は。明確化のために、typeofのecmascript仕様を確認してください。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どうかはすでに確認しています。関数であり、メソッドを実装しているので、それが関数であることがわかります。一方、以前は、のインスタンスになります。そのため、もに解決されます。MyFunc2CallMyFunc2calltypeoffunction constructorMyFunc2Function constructorinstanceoftrue
安全に使用できるものは何ですか?
どちらの場合でもわかるように、typeofここで関数を処理していることをオペレーターが正常にアサートできるため、は安全ですinstanceof。instanceofのインスタンスではないfunction declarationため、の場合は失敗しfunction declarationsますFunction constructor。
ベストプラクティス:
ゲイリー・ラファティが示唆され、最良の方法は、両方のtypeofとinstanceofを一緒に使用する必要があります。
function isFunction(functionItem) {
return typeof(functionItem) == 'function' || functionItem instanceof Function;
}
isFunction(MyFunc) // invoke it by passing our test function as parameter
上記の例のトンで圧倒する必要はありません。2つの観点に注意してください。
typeof var;単項演算子は、varの元の型またはルート型を返します。それは、プリミティブ型(返すことをstring、number、bigint、boolean、undefined、及びsymbol)またはobjectタイプを。
組み込みオブジェクト(String、Number、Boolean、Array ..)のような上位レベルのオブジェクト、または複雑なオブジェクトやカスタムオブジェクトの場合、それらはすべてobjectルートタイプですが、それらに基づいて構築されるインスタンスタイプはさまざまです(OOPクラスのように)継承の概念)、ここではa instanceof A-バイナリ演算子-が役立ちます。プロトタイプチェーンを通過して、正しいオペランド(A)のコンストラクタが表示されるかどうかを確認します。
したがって、「ルートタイプ」をチェックしたり、プリミティブ変数を操作したりするときはいつでも、「typeof」を使用してください。それ以外の場合は「instanceof」を使用してください。
nullは一見原始的である特別なケースですが、実際にはオブジェクトの特別なケースです。使用するa === null代わりにnullをチェックためにします。
一方、function組み込みオブジェクトである特殊なケースでもありますが、typeofリターンfunction
ご覧のinstanceofとおり、プロトタイプチェーンを通過する必要があります。一方typeof、ルートタイプを1回確認するだけで、なぜtypeofよりも高速であるかを簡単に理解できます。instanceof
typeofに関するMDNドキュメントによれば、「new」キーワードでインスタンス化されたオブジェクトは、タイプ 'object'です。
typeof 'bla' === 'string';
// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';
しばらくのinstanceofに関するドキュメント:ポイントその
const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true
したがって、作成方法に関係なく、何かが文字列であることを確認したい場合は、を使用するのが最も安全な方法instanceofです。