3

I'm actually trying to differentiate (in my code) functions and classes.

I need to know, in a simple console.log, if the parameter of my function is a class or a simple function.

I'm actually taking about class, not object, but really a class.

Like:

function(item){
    if(isClass(item)){
        console.log('it s a class !');
    }else{
        if(isFunc(item)){
            console.log('it s a function !');
         }
    }
}

Edit : angular 2 is able to distinguish a function and a class in his injector container class

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
mfrachet
  • 8,772
  • 17
  • 55
  • 110

3 Answers3

2

There aren't any classes in JavaScript. Though functions can be instanciated with the new keyword.

You can check if something is a function with instanceof:

var a = function() {};

a instanceof Function; // true

An instanciated function will be an instance of that specific function:

var b = new a();

b instanceof Function; // false
b instanceof a; // true
pstenstrm
  • 6,339
  • 5
  • 41
  • 62
1

There are no classes* in Javascript. Instead functions in JavaScript can act like constructors with the help of new keyword. (constructor pattern)

Objects in JavaScript directly inherit from other objects, hence we don't need classes. All we need is a way to create and extend objects.

You can use jQuery.isFunction() to check if the argument passed to isFunction() is a Javascript function object.

From the documentation:

jQuery.isFunction()

Description: Determine if the argument passed is a JavaScript function object.

EDIT: As rightly pointed out by user2867288, the statement that Javascript has no classes needs to be taken with a pinch of salt.

Read these articles for more information about the ECMAScript 6 standard:

Community
  • 1
  • 1
Srini
  • 1,626
  • 2
  • 15
  • 25
1

Constructors ("classes") are only functions. There's not much that differentiates them.

However, their usage is quite different. Classes do typically have methods and maybe even other properties on their prototype. And that's in fact how you can distinguish them.1
Bound functions and functions constructed using arrow notation (ES6) even don't have a prototype at all.

function isFunc(fn) {
    return typeof fn == "function" && (!fn.prototype || !Object.keys(fn.prototype).length);
}

1: not detecting atypical classes that don't make use of prototypical inheritance

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • This idea is used in the [Bluebird library](https://github.com/petkaantonov/bluebird/blob/634af0e27ff4faab62c6c5bfd105527abcf8b06e/src/util.js#L163). – Bergi May 30 '15 at 15:09
  • So, there is no reliable way to distinguish between a class (though it is a function in disguise) and a function, right? – thefourtheye May 30 '15 at 15:23
  • Yes, there is no reliable way. I'd say "*because* it is (disguised as) a function" :-) – Bergi May 30 '15 at 15:44
  • Not even ES6 classes are - though there is discussion whether `Reflect.isCallable` should return `false` for them. – Bergi May 30 '15 at 15:46
  • I was going through the spec to find if any of the internal slots which expose the actual type, but I couldn't :'( – thefourtheye May 30 '15 at 15:46
  • @thefourtheye: Well, there's the `[[FunctionKind]]` internal slot which is set to `"classConstructor"` for "classes" (constructor functions created using the `class` keyword), but it is an *internal* slot (used only to throw errors on `[[Call]]`) :-) – Bergi May 30 '15 at 15:54
  • Ya, but there is no function which can return that value. And `Reflect.isCallable` is not likely to land in ES6, right? – thefourtheye May 30 '15 at 15:58
  • Yes, exactly - that's why I emphasized "internal". And while ES6 is basically settled, even for `isCallable` there was discussion whether it should not better return `true` because even when constructor throw on not being used with `new`, they do still have a `[[call]]` slot like every other callable thing. – Bergi May 30 '15 at 17:38