Lodash _.functions and Asynchronous Class Methods
Lodash's _.functions method retrieves an array of
function property names from an object, but it does not differentiate
between strictly synchronous methods and asynchronous class methods.
Internally, Lodash evaluates all callable objects using its standard
type-checking utility, treating both standard functions and
AsyncFunction instances identically while relying strictly
on property enumeration rather than function execution traits.
Internal Function Identification
Lodash implements _.functions by iterating over an
object’s own enumerable properties and filtering them with an internal
check, primarily isFunction.
In modern JavaScript engines, an asynchronous function is an instance
of the hidden AsyncFunction constructor. However,
AsyncFunction.prototype inherits from
Function.prototype, and calling typeof on an
async method evaluates to "function". Lodash's internal
baseGetTag method inspects the [[Class]] tag
via Object.prototype.toString.call(value). Lodash
explicitly includes tags like [object Function],
[object AsyncFunction],
[object GeneratorFunction], and [object Proxy]
as valid functions. Because both synchronous and asynchronous functions
pass this predicate, _.functions groups them together
without distinction.
The Role of Class Method Enumerability
When working specifically with ES6 class methods, developers often encounter an additional layer of behavior: property enumerability.
- Standard Class Methods: Methods defined directly in
a class body (whether declared with
asyncor not) are placed on the class'sprototypeand are set toenumerable: falseby default. Because_.functionsonly inspects an object’s own enumerable properties using mechanisms similar toObject.keys, it will not extract traditional class methods—synchronous or asynchronous—from class instances unless_.functionsInis used or the prototype is inspected directly. - Public Class Field Methods: If methods are defined
as arrow functions or bound fields (e.g.,
syncMethod = () => {}orasyncMethod = async () => {}), they are assigned directly to the instance as own enumerable properties. In this case,_.functionsdetects both.
How to Manually Differentiate Sync and Async Methods
Because _.functions deliberately does not segregate
functions based on their return type or execution mechanism, separating
them requires custom JavaScript inspection using runtime metadata.
To identify strictly asynchronous methods, you must inspect the function constructor or its string tag:
const isAsync = (fn) => fn[Symbol.toStringTag] === 'AsyncFunction' || fn.constructor.name === 'AsyncFunction';Alternatively, synchronous methods that return a Promise at runtime
cannot be identified prior to execution without analyzing the returned
value via value instanceof Promise or checking for a
then method. Lodash avoids this level of runtime
introspection, maintaining _.functions as a structural
property lister rather than a method signature analyzer.