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 typeof
keine Option ist und Sie wissen, dass Sie sich nicht für die Prototypenkette interessieren , Object.prototype.constructor
kann 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 null
oder 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)
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)
Firefox 59.0b10 (64-Bit, Windows)
HINWEIS: Die Reihenfolge, in der die Funktionen aufgelistet sind, wechselt zwischen den Bildern!