Esto es sólo el conocimiento complementario a todas las otras explicaciones - estoy no sugiriendo utilizar .constructor
en todas partes.
TL; DR: en situaciones en las typeof
que no es una opción, y cuando sabe que no le importa la cadena de prototipos , Object.prototype.constructor
puede ser una alternativa viable o incluso mejor que instanceof
:
x instanceof Y
x.constructor === Y
Ha estado en el estándar desde 1.1, por lo que no se preocupe por la compatibilidad con versiones anteriores.
Muhammad Umer mencionó brevemente esto en un comentario en algún lugar aquí también. Funciona en todo con un prototipo, por lo que no todo 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
Además, dependiendo de su caso de uso, puede ser mucho más rápido que instanceof
(la razón probablemente sea que no tiene que verificar toda la cadena del prototipo). En mi caso, necesitaba una forma rápida de verificar si un valor es una matriz escrita:
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
Y los resultados:
Chrome 64.0.3282.167 (64 bits, Windows)
Firefox 59.0b10 (64 bits, Windows)
Por curiosidad, hice una referencia rápida de juguete en contra typeof
; Sorprendentemente no funciona mucho peor, y parece incluso un poco más rápido en 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: ¡El orden en que se enumeran las funciones cambia entre imágenes!
Chrome 64.0.3282.167 (64 bits, Windows)
Firefox 59.0b10 (64 bits, Windows)
NOTA: ¡El orden en que se enumeran las funciones cambia entre imágenes!