Was ist der Unterschied zwischen Typ und Instanz von und wann sollte einer gegenüber dem anderen verwendet werden?

394

In meinem speziellen Fall:

callback instanceof Function

oder

typeof callback == "function"

Ist es überhaupt wichtig, was ist der Unterschied?

Zusätzliche Ressource:

JavaScript-Garden typeof vs instanceof

Farinspace
quelle
2
Ich fand meine Antwort hier als einfach zu verwendende Lösung
CrandellWS
1
Es gibt eine andere Möglichkeit, den Typ mit Object.prototype.toString ecma-international.org/ecma-262/6.0/…
rab
1
Verwenden Sie .constructorstattdessen einfach die Eigenschaft.
Muhammad Umer
Wenn Sie sich über die Leistung wundern , lesen Sie meine Antwort unten . typeof ist schneller, wenn beide anwendbar sind (nämlich Objekte).
Martin Peter

Antworten:

540

Verwendung instanceoffür benutzerdefinierte Typen:

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 

Verwendung typeoffür einfache eingebaute Typen:

'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

Verwendung instanceoffür komplexe eingebaute Typen:

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

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

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

Und der letzte ist ein bisschen knifflig:

typeof null; // object
Szymon Wygnański
quelle
11
Diese Antwort macht deutlich, warum instaceof nicht für primitive Typen verwendet werden sollte. Es ist ziemlich offensichtlich, dass Sie keine Option haben, wenn es um benutzerdefinierte Typen geht, sowie den Vorteil für Objekttypen. Aber was macht Funktionen mit "einfachen eingebauten Typen" zusammengefasst? Ich finde es seltsam, wie sich eine Funktion wie ein Objekt verhält, aber ihr Typ ist 'Funktion', was die Verwendung von 'Typ von' möglich macht. Warum würden Sie Instanz davon jedoch entmutigen?
Assimilater
4
@Assimilater Sie könnten Instanz auch mit Funktionen verwenden, aber ich halte diese 3 Regeln für sehr einfach zu merken und ja, Funktionen sind eine Ausnahme :)
Szymon Wygnański
2
ein weiterer kniffliger Teil -> 'Beispielzeichenfolge' Instanz von Zeichenfolge; // false aber neuer String ('Beispielstring') instanceof String; // wahr
Luke
2
@ Luke ist im Allgemeinen eine schlechte Idee, "neue Zeichenfolge" wie diese zu verwenden. Dadurch wird eher ein "Zeichenfolgenobjekt" als ein Zeichenfolgenprimitiv erstellt. siehe Abschnitt hier developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Colin D
4
Use instanceof for complex built in types- Dies ist immer noch fehleranfällig. Besser ES5 Array.isArray()et al. oder die empfohlenen Unterlegscheiben.
OrangeDog
122

Beide sind in ihrer Funktionalität ähnlich, da beide Typinformationen zurückgeben. Ich persönlich bevorzuge instanceofes jedoch, weil sie tatsächliche Typen anstelle von Zeichenfolgen vergleichen. Der Typvergleich ist weniger anfällig für menschliches Versagen und technisch schneller, da Zeiger im Speicher verglichen werden, anstatt Vergleiche mit ganzen Zeichenfolgen durchzuführen.

Soviut
quelle
8
Es gibt einige Situationen, in denen instanceof nicht wie erwartet funktioniert und typeof gut funktioniert ... developer.mozilla.org/En/Core_JavaScript_1.5_Reference/…
farinspace
55
instanceof arbeitet mit Objekten im selben Fenster. Wenn Sie iframe / frame oder Popup-Fenster verwenden, hat jedes (i) Frame / Fenster ein eigenes "Funktions" -Objekt und die Instanz von schlägt fehl, wenn Sie versuchen, ein Objekt aus einem anderen (i) Frame / Fenster zu vergleichen. typeof funktioniert in allen Fällen, da die Zeichenfolge "function" zurückgegeben wird.
einige
14
jsperf.com/typeof-function-vs-instanceof/3 Ich habe Chrome und FF3.X ausprobiert. Der "typeof" -Ansatz ist schneller.
Morgan Cheng
10
Das ist einfach falsch. Sie sind nicht identisch. Sie funktionieren nicht in allen Situationen, insbesondere in verschiedenen JavaScript-VMs und Browsern.
Justin Force
8
Ihre Antwort lautet: "Beide sind in Bezug auf die Funktionalität im Wesentlichen identisch." Respektvoll ist dies offensichtlich falsch. Wie in meiner Antwort beschrieben und erläutert, funktioniert keine der beiden Optionen in jeder Situation - insbesondere in allen Browsern. Der bessere Ansatz ist, beide mit einem || zu verwenden Operator.
Justin Force
103

Ein guter Grund für die Verwendung von typeof ist, wenn die Variable möglicherweise undefiniert ist.

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

Ein guter Grund für die Verwendung von instanceof ist, wenn die Variable null sein kann.

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

Meiner Meinung nach hängt es also wirklich davon ab, welche Art von möglichen Daten Sie überprüfen.

Kenneth J.
quelle
11
+1 Beachten Sie auch, dass instanceofnicht mit primitiven Typen zu vergleichen ist, typeof can.
Tino
3
In Chrome 29.0.1541.0 gibt dev undefined instanceof Objectfalse zurück und löst keine Ausnahme aus. Ich weiß nicht, wie aktuell diese Änderung ist, aber sie macht instanceofattraktiver.
Cypress Frankenfeld
7
undefined instanceof Objectlöst keine Ausnahme aus, weil eh undefineddefiniert ist. Die Konstante existiert im Namespace. Wenn eine Variable nicht vorhanden ist (z. B. aufgrund eines Tippfehlers), löst instanceof eine Ausnahme aus. Die Verwendung von typeof für eine nicht vorhandene Variable ergibt andererseits 'undefined'.
Cleong
31

Um die Dinge klar zu machen, müssen Sie zwei Fakten kennen:

  1. Die Instanz des Operators testet, ob die Prototyp-Eigenschaft eines Konstruktors irgendwo in der Prototypenkette eines Objekts angezeigt wird. In den meisten Fällen ist dies bedeuten , dass das Objekt erstellt mithilfe dieser Konstruktor oder auf seiner Nachkommen. Der Prototyp kann aber auch explizit nach Object.setPrototypeOf()Methode (ECMAScript 2015) oder nach __proto__Eigenschaft (alte Browser, veraltet) festgelegt werden. Das Ändern des Prototyps eines Objekts wird aus Leistungsgründen jedoch nicht empfohlen.

Somit gilt instanceof nur für Objekte. In den meisten Fällen verwenden Sie keine Konstruktoren, um Zeichenfolgen oder Zahlen zu erstellen. Du kannst. Aber das tust du fast nie.

Auch instanceof kann nicht genau prüfen, welcher Konstruktor zum Erstellen des Objekts verwendet wurde, gibt jedoch true zurück, selbst wenn das Objekt von der zu überprüfenden Klasse abgeleitet ist. In den meisten Fällen ist dies das gewünschte Verhalten, manchmal jedoch nicht. Also musst du diesen Geist behalten.

Ein weiteres Problem besteht darin, dass unterschiedliche Bereiche unterschiedliche Ausführungsumgebungen haben. Dies bedeutet, dass sie unterschiedliche integrierte Funktionen haben (unterschiedliche globale Objekte, unterschiedliche Konstruktoren usw.). Dies kann zu unerwarteten Ergebnissen führen.

Zum Beispiel [] instanceof window.frames[0].Arraywird zurückkehren false, weil Array.prototype !== window.frames[0].Arrayund Arrays aus dem ehemaligen erben.
Es kann auch nicht für undefinierte Werte verwendet werden, da es keinen Prototyp hat.

  1. Der Operator typeof prüft, ob der Wert zu einem von sechs Grundtypen gehört : " number ", " string ", " boolean ", " object ", " function " oder " undefined ". Wobei die Zeichenfolge "Objekt" zu allen Objekten gehört (mit Ausnahme von Funktionen, die Objekte sind, aber einen eigenen Wert im Typ des Operators haben) sowie zu "Null" -Werten und Arrays (für "Null" ist es ein Fehler, aber dieser Fehler ist so alt , so ist es ein Standard geworden). Es ist nicht auf Konstruktoren angewiesen und kann verwendet werden, auch wenn der Wert nicht definiert ist. Es gibt jedoch keine Details zu Objekten. Wenn Sie es also brauchen, gehen Sie zu instanceof.

Lassen Sie uns jetzt über eine schwierige Sache sprechen. Was ist, wenn Sie den Konstruktor verwenden, um einen primitiven Typ zu erstellen?

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

Scheint wie Magie. Aber es ist nicht. Es ist das sogenannte Boxen (Umschließen des primitiven Werts nach Objekt) und das Unboxing (Extrahieren des umschlossenen primitiven Werts aus dem Objekt). Eine solche Art von Code scheint "ein bisschen" zerbrechlich zu sein. Natürlich können Sie es einfach vermeiden, mit Konstruktoren einen primitiven Typ zu erstellen. Aber es gibt noch eine andere mögliche Situation, in der das Boxen Sie treffen kann. Wenn Sie Function.call () oder Function.apply () für einen primitiven Typ verwenden.

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

Um dies zu vermeiden, können Sie den strengen Modus verwenden:

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

upd: Seit ECMAScript 2015 gibt es einen weiteren Typ namens Symbol, der einen eigenen Typ von == "Symbol" hat .

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

Sie können darüber auf MDN lesen: ( Symbol , Typ ).

Vladimir Liubimov
quelle
2
if an object is created by a given constructor Das ist falsch. o instanceof Cwird true zurückgeben, wenn o von C.prototype erbt. Sie haben später in Ihrer Antwort etwas darüber erwähnt, aber es ist nicht sehr klar.
Oyenamit
1
falsch ... aus dem Buch: " github.com/getify/You-Dont-Know-JS " eine Instanz von Foo; // true Der Operator instanceof verwendet ein einfaches Objekt als linken Operanden und eine Funktion als rechten Operanden. Die Frage Instanz der Antworten lautet: Erscheint in der gesamten [[Prototype]] - Kette von a das Objekt, auf das Foo.prototype willkürlich zeigt, jemals?
Deen John
1
Ich habe die Antwort bearbeitet, um korrekter zu sein. Vielen Dank für Ihre Kommentare.
Vladimir Liubimov
Außerdem wurde eine Erläuterung des Box- / Unboxing-Problems hinzugefügt.
Vladimir Liubimov
15

Ich habe in Safari 5 und Internet Explorer 9 ein wirklich interessantes (als "schrecklich" bezeichnetes) Verhalten entdeckt. Ich habe es in Chrome und Firefox mit großem Erfolg verwendet.

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

Dann teste ich in IE9 und es funktioniert überhaupt nicht. Große Überraschung. Aber in Safari ist es zeitweise! Also beginne ich mit dem Debuggen und stelle fest, dass Internet Explorer immer wieder zurückkehrt false. Aber das Seltsamste ist, dass Safari anscheinend eine Art Optimierung in seiner JavaScript-VM vornimmt, wo es truedas erste Mal ist, aber jedes Mal , wenn false Sie auf "Neu laden" klicken!

Mein Gehirn explodierte fast.

Jetzt habe ich mich also darauf geeinigt:

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

Und jetzt funktioniert alles super. Beachten Sie, dass Sie aufrufen können "a string".toString()und nur eine Kopie der Zeichenfolge zurückgibt, d. H.

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

Also werde ich von nun an beide verwenden.

Justin Force
quelle
8

Sonstige wesentliche praktische Unterschiede:

// 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
Amjad Farajallah
quelle
7

instanceoffunktioniert auch, wenn callbackein Subtyp von ist Function, denke ich

newacct
quelle
4

instanceofin Javascript kann schuppig sein - ich glaube, große Frameworks versuchen, seine Verwendung zu vermeiden. Verschiedene Fenster sind eine der Möglichkeiten, wie sie brechen können - ich glaube, Klassenhierarchien können es auch verwirren.

Es gibt bessere Möglichkeiten, um zu testen, ob ein Objekt ein bestimmter integrierter Typ ist (was normalerweise gewünscht wird). Erstellen Sie Dienstprogrammfunktionen und verwenden Sie sie:

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

Und so weiter.

Levik
quelle
2
Falls Sie nicht wussten: typeof benötigt keine Klammern, da es sich um ein Schlüsselwort und keine Funktion handelt. Und IMHO sollten Sie === anstelle von == verwenden.
einige
5
@some Sie haben Recht mit typeof, aber in diesem Fall ist === nicht erforderlich. Es wird nur benötigt, wenn der verglichene Wert gleich sein kann, ohne denselben Typ zu haben. Hier kann es nicht.
Nicole
@some Gibt typeof jemals etwas anderes als einen String zurück?
Kenneth J
IsArray wäre also beispielsweise für ein Stapelobjekt mit einer Push-Methode und einem numerischen Längenattribut falsch. Unter welchen Umständen wäre (Instanz von Array) falsch?
Chris Noe
@ChrisNoe Das Problem tritt bei Objekten auf, die von mehreren Frames gemeinsam genutzt werden: groups.google.com/forum/#!msg/comp.lang.javascript/XTWYCOwC96I/…
3

instanceofwird nicht für Grundelemente funktionieren, z. B. "foo" instanceof Stringwird zurückkehren, falsewährend typeof "foo" == "string"wird zurückkehrentrue .

Auf der anderen Seite typeofwird es wahrscheinlich nicht das tun, was Sie wollen, wenn es um benutzerdefinierte Objekte (oder Klassen, wie auch immer Sie sie nennen möchten) geht. Zum Beispiel:

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

Es kommt einfach so vor, dass Funktionen sowohl 'Funktions'-Primitive als auch Instanzen von' Funktion 'sind, was etwas seltsam ist, da es für andere primitive Typen, z.

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

aber

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

Ich würde die Verwendung von Prototypen empfehlen callback.isFunction().

Sie haben den Unterschied herausgefunden und Sie können sich auf ihren Grund verlassen.

Ich denke, andere JS-Frameworks haben auch solche Dinge.

instanceOfIch glaube, ich würde nicht an Funktionen arbeiten, die in anderen Fenstern definiert sind. Ihre Funktion unterscheidet sich von Ihrer window.Function.

Alamar
quelle
3

Bei der Suche nach einer Funktion muss immer verwendet werden typeof.

Hier ist der Unterschied:

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

Deshalb darf man niemals instanceofnach einer Funktion suchen.

vitaly-t
quelle
Ich kann argumentieren, typeofdass es falsch ist - fist alles Folgendes: ein Object(ein Objekt) und ein Function(eine Funktion). Mit Ausnahme von mir ist die Verwendung sinnvoller, instanceofda ich weiß, dass es sich um eine Funktion handelt, von der ich weiß, dass es sich auch um ein Objekt handelt, da alle Funktionen Objekte in ECMAScript sind. Das Gegenteil ist nicht wahr - aus dem Wissen , typeofdass fist in der Tat ein objectIch habe keine Ahnung , dass es auch eine Funktion.
amn
@amn Für mich ist es eine kaputte Instanz von Function. Es wird Attribute wie length, nameund callvon Funktion, aber alle von ihnen sind nicht mehr. Was noch schlimmer ist, es kann nicht aufgerufen werden und das TypeErrorsagt es : f is not a function.
Maaartinus
2

Wesentlicher praktischer Unterschied:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Frag mich nicht warum.

Barney
quelle
11
Denn hier strist ein String-Grundelement, kein String-Objekt. Das Gleiche gilt für Zahlenprimitive und Boolesche Grundelemente. Sie sind keine Instanzen ihrer "konstruierten" Gegenstücke, der String-, Zahlen- und Booleschen Objekte. JavaScript konvertiert diese drei Grundelemente bei Bedarf automatisch in Objekte (z. B. mithilfe einer Methode in der Prototypenkette des Objekts). Auf der anderen Seite Ihres praktischen Unterschieds ist instanceof seitdem besser für die Suche nach Arrays geeignet typeof [] == "object" // true.
Andy E
2

Performance

typeof ist schneller als instanceof in Situationen, in denen beide anwendbar sind.

Abhängig von Ihrem Motor kann der Leistungsunterschied zugunsten von typeofetwa 20% liegen . ( Ihr Kilometerstand kann variieren )

Hier ist ein Benchmark-Test für 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));

Ergebnis

instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
Martin Peter
quelle
1
typeof subject == "array" sollte false zurückgeben. Typ des Subjekts ist "Objekt".
Shardul
Wie kommt es, dass der Typ schneller ist? Interniert Javascript die wörtlichen Zeichenfolgen?
Gregory Magarshak
Der Grund ist: folgt instanceof immer der Prototypenkette des Objekts, sodass die Leistungsbeeinträchtigung davon abhängt, inwieweit in der Prototypenkette die Klasse instanceofgetestet wird. Für eine kurze Vererbungskette ist die Strafe also niedriger (wie [] instanceof Array,, {} instanceof Object) und für lange - größer. Wenn also beide obj instanceof SomeClassund typeof obj !== 'string'aus der Sicht einiger Ihrer hypothetischen Codes dasselbe bedeuten (z. B. wenn Sie nur einen Test durchführen ifund nicht switchmehrere Klassen durchlaufen usw.), sollten Sie in Bezug auf die Leistung die zweite auswählen.
Ankhzet
2

Dies ist nur eine Ergänzung zu allen anderen Erklärungen hier - ich schlage nicht vor , sie .constructorüberall zu verwenden .

TL; DR: In Situationen, in denen dies typeofkeine Option ist und Sie wissen, dass Sie sich nicht für die Prototypenkette interessieren , Object.prototype.constructorkann dies eine praktikable oder sogar bessere Alternative sein als instanceof:

x instanceof Y
x.constructor === Y

Es ist seit 1.1 im Standard, also keine Sorge um die Abwärtskompatibilität.

Muhammad Umer erwähnte dies auch hier irgendwo in einem Kommentar kurz. Es funktioniert auf alles mit einem Prototyp - also alles nicht nulloder 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

Darüber hinaus kann es je nach Anwendungsfall viel schneller sein als instanceof(der Grund dafür ist wahrscheinlich, dass nicht die gesamte Prototypenkette überprüft werden muss). In meinem Fall brauchte ich einen schnellen Weg, um zu überprüfen, ob ein Wert ein typisiertes Array ist:

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

Und die Ergebnisse:

Chrome 64.0.3282.167 (64-Bit, Windows)

Typisierte Array-Instanz von vs Konstruktor - 1,5-mal schneller in Chrome 64.0.3282.167 (64-Bit, Windows)

Firefox 59.0b10 (64-Bit, Windows)

Typisierte Array-Instanz von vs Konstruktor - 30x schneller in Firefox 59.0b10 (64-Bit, Windows)

Aus Neugier habe ich einen schnellen Spielzeug-Benchmark durchgeführt typeof; überraschenderweise ist die Leistung nicht viel schlechter und in Chrome scheint es sogar noch ein bisschen schneller zu sein:

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

HINWEIS: Die Reihenfolge, in der die Funktionen aufgelistet sind, wechselt zwischen den Bildern!

Chrome 64.0.3282.167 (64-Bit, Windows)

String / Number typeof vs constructor - 1,26x schneller in Chrome 64.0.3282.167 (64-Bit, Windows)

Firefox 59.0b10 (64-Bit, Windows)

HINWEIS: Die Reihenfolge, in der die Funktionen aufgelistet sind, wechselt zwischen den Bildern!

String / Number typeof vs constructor - 0,78x langsamer in Firefox 59.0b10 (64-Bit, Windows)

Job
quelle
1

Verwenden Sie instanceof, da beim Ändern des Klassennamens ein Compilerfehler angezeigt wird.

Robert
quelle
1

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"

xgqfrms
quelle
Was soll ich tun, kann ich UA (navigator.userAgent) bekommen?
xgqfrms
0

Ich komme aus einer strengen OO-Erziehung, für die ich mich entscheiden würde

callback instanceof Function

Strings sind anfällig für meine schreckliche Rechtschreibung oder andere Tippfehler. Außerdem finde ich, dass es besser liest.

Keplerf1
quelle
0

Obwohl Instanz ein bisschen schneller als Typ ist , bevorzuge ich wegen einer solchen möglichen Magie die zweite:

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
Suprido
quelle
0

Ein weiterer Fall ist, dass Sie nur mit sortieren können instanceof- es gibt true oder false zurück. Mit typeofkönnen Sie Art von etwas zur Verfügung gestellt bekommen

Jarosław Wlazło
quelle
0

Mit Blick auf die Leistung sollten Sie typeof besser mit einer typischen Hardware verwenden. Wenn Sie ein Skript mit einer Schleife von 10 Millionen Iterationen erstellen, dauert die Anweisung typeof str == 'string' 9 ms, während die 'string'-Instanz von String 19 ms dauert

Khalid Rafik
quelle
0

Natürlich ist es wichtig ........!

Lassen Sie uns dies anhand von Beispielen durchgehen. In unserem Beispiel werden wir die Funktion auf zwei verschiedene Arten deklarieren.

Wir werden beide function declarationund Function Constructor verwenden . Wir werden sehen, wie typeofund wie wir uns instanceofin diesen beiden unterschiedlichen Szenarien verhalten.

Funktion mit Funktionsdeklaration erstellen:

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

Mögliche Erklärung für ein solches anderes Ergebnis ist, wie wir eine Funktion Erklärung, typeofkann verstehen , dass es sich um eine function.Because ist typeofüberprüft , ob der Ausdruck auf dem typeof Betrieb ist, in unserem Fall implementiert Call - Methode oder nicht . Wenn es eine Methode implementiert , handelt es sich um eine Funktion. Andernfalls nicht. Zur Verdeutlichung überprüfen Sie die Ecmascript-Spezifikation auf den TypMyFunc Call .

Erstellen Sie eine Funktion mit dem Funktionskonstruktor:

var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used 

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

Hier typeofbehauptet , dass MyFunc2eine Funktion sowie die instanceofoperator.We bereits weiß , zu typeofüberprüfen , ob MyFunc2implementiert CallMethode oder not.As MyFunc2eine Funktion ist , und es implementiert callMethode, das ist , wie typeofweiß , dass es ein function.On ist die andere Hand, verwenden wir function constructorzu schaffen , um MyFunc2es wird zu einer Instanz von Function constructor. Deshalb wird instanceofauch aufgelöst true.

Was ist sicherer zu verwenden?

Wie wir in beiden Fällen sehen typeofkönnen, kann der Bediener erfolgreich behaupten, dass es sich hier um eine Funktion handelt, die sicherer ist als instanceof. instanceofwird im Falle von scheitern, function declarationweil function declarationskeine Instanz von sind Function constructor.

Beste Übung :

Wie Gary Rafferty vorgeschlagen hat, sollte der beste Weg darin bestehen, sowohl typeof als auch instanceof zusammen zu verwenden.

  function isFunction(functionItem) {

        return typeof(functionItem) == 'function' || functionItem instanceof Function;

  }

  isFunction(MyFunc) // invoke it by passing our test function as parameter
AL-Zami
quelle
Jede konstruktive Kritik bezüglich dieser Antwort wird geschätzt.
AL-Zami
0

Um genau zu sein, sollte eine Instanz verwendet werden, bei der Wert über den Konstruktor erstellt wird (im Allgemeinen benutzerdefinierte Typen), z

var d = new String("abc")

während typeof , um Werte zu überprüfen, die nur durch Zuweisungen für z

var d = "abc"
Sambhav
quelle
0

Sie müssen nicht mit einer Menge der oben genannten Beispiele überhäufen. Denken Sie nur an zwei Gesichtspunkte:

  1. typeof var;ist ein unärer Operator, der den ursprünglichen Typ oder Root-Typ von var zurückgibt. so dass es vom Urtyp zurückkehren ( string, number, bigint, boolean, undefined, und symbol) oder objectTyp.

  2. Bei übergeordneten Objekten wie integrierten Objekten (String, Number, Boolean, Array ..) oder komplexen oder benutzerdefinierten Objekten handelt es sich bei allen Objekten um objectStammtypen. Der darauf basierende Instanztyp ist jedoch unterschiedlich (wie bei der OOP-Klasse) Vererbungskonzept), hier a instanceof A- ein binärer Operator - hilft Ihnen, er durchläuft die Prototypenkette, um zu überprüfen, ob der Konstruktor des richtigen Operanden (A) erscheint oder nicht.

Wenn Sie also "Root-Typ" überprüfen oder mit primitiven Variablen arbeiten möchten, verwenden Sie "typeof", andernfalls "instanceof".

nullist ein Sonderfall, der scheinbar primitiv ist, aber in der Tat ein Sonderfall für Objekt. Verwenden a === nullSie stattdessen, um null zu überprüfen.

Auf der anderen Seite functionist auch ein Sonderfall, der ein eingebautes Objekt ist, aber typeofzurückgibtfunction

Wie Sie sehen, instanceofmuss die Prototypenkette in der Zwischenzeit typeofnur einmal den Wurzeltyp überprüfen, damit leicht zu verstehen ist, warum dies typeofschneller ist alsinstanceof

Lam Phan
quelle
0

Gemäß der MDN-Dokumentation zu typeof sind Objekte, die mit dem Schlüsselwort "new" instanziiert wurden, vom Typ "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';

Während die Dokumentation über Instanz von Punkten, dass:

const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true

Wenn man also überprüfen möchte, ob etwas eine Zeichenfolge ist, unabhängig davon, wie es erstellt wurde, ist es am sichersten, es zu verwenden instanceof.

Laszlo Sarvold
quelle