In ECMAScript 6 the typeof
of classes is, according to the specification, \'function\'
.
However also according to the specification you are
Ran some performance benchmarks on the different approaches mentioned in this thread, here is an overview:
Native Class - Props Method (fastest by 56x on large examples, and 15x on trivial examples):
function isNativeClass (thing) {
return typeof thing === 'function' && thing.hasOwnProperty('prototype') && !thing.hasOwnProperty('arguments')
}
Which works because the following is true:
> Object.getOwnPropertyNames(class A {})
[ 'length', 'name', 'prototype' ]
> Object.getOwnPropertyNames(class A { constructor (a,b) {} })
[ 'length', 'name', 'prototype' ]
> Object.getOwnPropertyNames(class A { constructor (a,b) {} a (b,c) {} })
[ 'length', 'name', 'prototype' ]
> Object.getOwnPropertyNames(function () {})
[ 'length', 'name', 'arguments', 'caller', 'prototype' ]
> Object.getOwnPropertyNames(() => {})
> [ 'length', 'name' ]
Native Class - String Method (faster than regex method by about 10%):
/**
* Is ES6+ class
* @param {any} value
* @returns {boolean}
*/
function isNativeClass (value /* :mixed */ ) /* :boolean */ {
return typeof value === 'function' && value.toString().indexOf('class') === 0
}
This may also be of use for determining a Conventional Class:
// Character positions
const INDEX_OF_FUNCTION_NAME = 9 // "function X", X is at index 9
const FIRST_UPPERCASE_INDEX_IN_ASCII = 65 // A is at index 65 in ASCII
const LAST_UPPERCASE_INDEX_IN_ASCII = 90 // Z is at index 90 in ASCII
/**
* Is Conventional Class
* Looks for function with capital first letter MyClass
* First letter is the 9th character
* If changed, isClass must also be updated
* @param {any} value
* @returns {boolean}
*/
function isConventionalClass (value /* :any */ ) /* :boolean */ {
if ( typeof value !== 'function' ) return false
const c = value.toString().charCodeAt(INDEX_OF_FUNCTION_NAME)
return c >= FIRST_UPPERCASE_INDEX_IN_ASCII && c <= LAST_UPPERCASE_INDEX_IN_ASCII
}
I'd also recommend checking out my typechecker package which includes the use cases for the above - via the isNativeClass
method, isConventionalClass
method, and a isClass
method that checks for both types.