Tom
Tom

Reputation: 17864

How to differentiate a function from a class object?

I have a js object that could be a function or a class, ie. it is equal to one of:

class {
  constructor( param ) {  }
  onCreate() { } 
};

Or,

function ( param ) { };

Turns out they have more in common then I expected (eg. both have a constructor). Please tell me the simplest way to determine which of these types my js object refers to.

The solution must work in node 4.3.2.

edit: To clarify, the object that I'm trying to differentiate is a class or a function, not an instance of these. And yes, I'm aware that a class is just syntatic sugar, that's what is making this difficult.

Upvotes: 1

Views: 244

Answers (4)

jcollum
jcollum

Reputation: 46599

The answer to these sorts of questions is almost always Lodash (or Underscore). Lodash has isFunction:

Checks if value is classified as a Function object.

There are a TON of things in Lodash that people try to re-create all the time. Lodash is almost certainly doing it the right way and it's well-maintained.

Moral of the story: check if Lodash does X before you write a function to do X.

coffee> ld.isFunction
[Function: isFunction]
coffee> ld.isFunction(Date)
true
coffee> a = b:2
{ b: 2 }
coffee> ld.isFunction(a) 
false
coffee> 
coffee> d = new Date()
2016-12-17T00:02:58.950Z
coffee> ld.isFunction(d) 
false

Upvotes: 0

Tom
Tom

Reputation: 17864

I thought it worth adding that, if one knows the names of the class or function, you can distinguish them like this.

> const C = class CC { };
undefined
> const F = function FF() { };
undefined
> C.prototype
CC {}
> F.prototype
FF {}

And if they are anonymous (not sure if that terminology is used in js) then you get just '{}'.

In a program you can use util.inspect (the name part dissapears with toString) to get at these strings.

Upvotes: 0

Ben Aston
Ben Aston

Reputation: 55749

A class is not a "real thing" in the JavaScript specification beyond being syntactic sugar for the composition of pre-existing language primitives.

Vendors may make distinction possible (e.g. the toString method suggested in another answer), but I have scanned the spec and I don't think that is part of it... so is vendor-defined and therefore cannot be relied upon.

Indeed: Firefox 50 on the Mac does not print the word "class" (it uses the word "function") when toString is used on a class.

I don't know much about JS classes, so I could be wrong...

Upvotes: 2

elclanrs
elclanrs

Reputation: 94111

I get this in the REPL with v6.9.2:

λ node -i
> class A {}
[Function: A]
> let B = function() {}
undefined
> A.toString()
'class A {}'
> B.toString()
'function () {}'

There may be another more reliable way, but checking for class should work:

if (A.toString().match(/^class/)) {
  // it's a class
}

Upvotes: 1

Related Questions