Quiero poder verificar si una función es de un tipo de clase determinado en javascript. Por ejemplo, digamos que tengo dos clases:
class Horse {} class Chicken {}Y digamos que quiero crear una función que me diga si una función pasada es Horse, algo así:
function isHorseClass(func) { // check if func is of Horse class type return isHorse; }La función será llamada de la siguiente manera:
isHorseClass(Horse) // should return true isHorseClass(Chicken) // should return false Tenga en cuenta que la clase se pasa dinámicamente sin instanciar el objeto de una clase, por lo que no puedo usar instanceof de para verificar el tipo aquí. ¿Hay alguna forma de verificar el tipo de clase dinámicamente, como en el ejemplo anterior?
Simplemente cree una instancia y verifique usando el operador instanceof .
class Horse {} class Dog {} class SubHorse extends Horse {} function isHorseClass(Cls) { const instance = new Cls(); return instance instanceof Horse; } console.log(isHorseClass(Horse)); console.log(isHorseClass(Dog)); console.log(isHorseClass(SubHorse)); La respuesta anterior devuelve verdadero incluso para las subclases de Horse , si solo desea una coincidencia exacta, use const isHorseClass = () => Cls === Horse .
Para una coincidencia exacta , puede usar === :
function isHorseClass(func) { return func === Horse; } function isHorseClass(func) { return func === Horse; } class Horse {} class Chicken {} console.log("Horse", isHorseClass(Horse)); // true console.log("Chicken", isHorseClass(Chicken)); // false ... pero si también quiere ser true para las subclases de Horse , entonces eso es posible con la sintaxis de class (no tanto con la sintaxis ES5 anterior, pero siga leyendo). Puedes hacerlo:
function isHorseClass(func) { while (func && func !== Function.prototype) { if (func === Horse) { return true; } func = Object.getPrototypeOf(func); } return false; } Eso funciona porque la sintaxis de class establece dos líneas de herencia: una para el prototipo asignado a las instancias y otra diferente para las funciones del constructor. Por ejemplo:
class Horse {} class Thoroughbred extends Horse {}Eso crea estas dos cadenas:
Pura sangre.prototipo −−−−> Caballo.prototipo −−−−> Objeto.prototipo Pura sangre −−−−> Caballo −−−> Función.prototipo
Esto es bastante exclusivo de JavaScript. :-)
Ejemplo en vivo:
function isHorseClass(func) { while (func && func !== Function.prototype) { if (func === Horse) { return true; } func = Object.getPrototypeOf(func); } return false; } class Horse {} class Thoroughbred extends Horse {} class Chicken {} console.log("Horse", isHorseClass(Horse)); // true console.log("Thoroughbred", isHorseClass(Thoroughbred)); // true console.log("Chicken", isHorseClass(Chicken)); // false Sin embargo, con ES5 (incluidas las versiones estándar de cómo se transpila la sintaxis de class a ES5), no puede hacerlo porque generalmente no configuran la herencia de la función del constructor (porque no podría hacerlo sin las características de ES2015+). Sin embargo, puede acercarse comprobando solo la cadena de prototipos. Combinando eso con la versión anterior:
function isHorseClass(func) { while (func && func !== Function.prototype) { if (func === Horse || func.prototype === Horse.prototype) { return true; } func = Object.getPrototypeOf(func); } return false; }Eso producirá falsos positivos. Por ejemplo, si hiciera esto:
function Horse() { } function Unrelated() { } Unrelated.prototype = Horse.prototype; ...produciría un falso positivo para Unrelated .