Septagram
Septagram

Reputation: 9795

Can you make an object 'callable'?

Is it possible to make an object callable by implementing either call or apply on it, or in some other way? E.g.:

var obj = {};
obj.call = function (context, arg1, arg2, ...) {
    ...
};

...

obj (a, b);

Upvotes: 64

Views: 38866

Answers (5)

0xc0de
0xc0de

Reputation: 8307

ES6 has better solution for this now. If you create your objects in a different way (using class, extending 'Function' type), you can have a callable instance of it.

See also: How to extend Function with ES6 classes?

Upvotes: 31

Fox
Fox

Reputation: 1

"CALLABLE OBJECTS"
I haven't seen mention of this type of answer yet.. but this is how I do "callable" objects:
<< PSEUDO CODE >>

{...objectWithFunctionsInside}[keyString](optionalParams)

short example defining first, simplest and preferred method if I just want a "callable object," in my definition:

let obj = { 
  o:()=>{return("oranges")},
  b:()=>{return("bananas")},
  s:"something random here, doesn't have to be functions"
}
obj["o"]()

short example of nameless object being run within a function's return, with parameters (note parameters works in the first example too):

function autoRunMyObject(choice,param){
  return{
    o:(p)=>{return(p+"oranges")},
    b:(p)=>{return(p+"bananas")},
  }[choice](param)
}
autoRunMyObject("b","orange you glad I didn't say ")

and that's pretty much it You could even get weirder with it and do nameless functions that auto-run themselves and produce an output right away... for no reason, lol. ... hit F12 and copy this code into your browser console and press enter, you'll get an output right away with the full string:

((autoparam="o")=>{return{
  o:(p)=>p+"oranges",
  b:(p)=>p+"bananas",
}[autoparam]("I guess this time it's ")})()

You could even pass in the string of "b" in the final parenthesis for a different output from the default "o".

Also, each of my examples (minus the pseudo code first example) are easily copy/paste-able into the browser console for quick testing -- it's a nice place to experiment with JS.

In summary -- this is how I like to do "callable objects"
It's much better than
SWITCH(){CASE:BREAK;};
statements and
IF{}ELSE IF(){}ELSE IF(){};
chains.

Upvotes: -2

Brasten Sager
Brasten Sager

Reputation: 138

Others have provided the current answer ("no") and some workarounds. As far as first-class support in the future, I suggested this very thing to the es-discuss mailing list. The idea did not get very far that time around, but perhaps some additional interest would help get the idea moving again.

https://esdiscuss.org/topic/proposal-default-object-method

Upvotes: 7

Rodrigo Rodrigues
Rodrigo Rodrigues

Reputation: 8576

Following the same line of @Max, but using ES6 extensions to Object to pass all properties and prototype of an object obj to the callable func.

Object.assign(func, obj);
Object.setPrototypeOf(func, Object.getPrototypeOf(obj));

Upvotes: 15

Max
Max

Reputation: 5091

No, but you can add properties onto a function, e.g.

function foo(){}
foo.myProperty = "whatever";

EDIT: to "make" an object callable, you'll still have to do the above, but it might look something like:

// Augments func with object's properties
function makeCallable(object, func){
    for(var prop in object){
        if(object.hasOwnProperty(prop)){
            func[prop] = object[prop];
        }
    }
}

And then you'd just use the "func" function instead of the object. Really all this method does is copy properties between two objects, but...it might help you.

Upvotes: 42

Related Questions