Questo è solo conoscenze complementari a tutte le altre spiegazioni qui - sto , non suggerendo di utilizzare .constructor
ovunque.
TL; DR: in situazioni in cui typeof
non è disponibile un'opzione e quando sai che non ti interessa la catena del prototipo , Object.prototype.constructor
può essere un'alternativa praticabile o addirittura migliore di instanceof
:
x instanceof Y
x.constructor === Y
È nello standard dall'1.1, quindi non preoccuparti della compatibilità con le versioni precedenti.
Muhammad Umer lo ha brevemente menzionato in un commento da qualche parte anche qui. Funziona su tutto con un prototipo, quindi non tutto null
o 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
Inoltre, a seconda del caso d'uso, può essere molto più veloce di instanceof
(il motivo è probabilmente che non deve controllare l'intera catena del prototipo). Nel mio caso avevo bisogno di un modo rapido per verificare se un valore è un array tipizzato:
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
E i risultati:
Chrome 64.0.3282.167 (64 bit, Windows)
Firefox 59.0b10 (64 bit, Windows)
Per curiosità, ho fatto un rapido benchmark del giocattolo contro typeof
; sorprendentemente non funziona molto peggio, e sembra anche un po 'più veloce in 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
NOTA: l'ordine in cui sono elencate le funzioni cambia tra le immagini!
Chrome 64.0.3282.167 (64 bit, Windows)
Firefox 59.0b10 (64 bit, Windows)
NOTA: l'ordine in cui sono elencate le funzioni cambia tra le immagini!