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.