3

In JavaScript, functions are objects, except that they can be called and executed, this is comparable to overloading the () operator of an object in other languages.

Can I apply this functionality to any object?

I know there isn't a property like [Symbol.call] or something comparable. If there is something comparable, I would greatly appreciate it if you could inform me of what it is.

If declaring objects and assigning properties to them is my only option that's okay, but I'd prefer if this could be done using a class, like C++ for example.

I could do something like this

function func(...) {
...
}

func.foo = x,
func.bar = y;

but it would be more preferable if I could do something more like

const func = {

    [`()`]: function(...) {
    ...
    },
    foo: x,
    bar: y
};
0

3 Answers 3

3

Can I apply this functionality to any object?“

No. As of ECMAScript 10th Edition (2019) this is not possible.

The ()-operator/expression construct can only be used on function objects.

This is because it uses the [[Call]] internal method. Section 7.3.12 Call indicates this is only defined for function objects and the specification makes no provision to add the [[Call]] internal method to other objects.

7.3.12 Call ( F, V [ , argumentsList ] )

The abstract operation Call is used to call the [[Call]] internal method of a function object. [..]

The specification is written in such a way that a future revision might add generalized support.

Anyway, as shown in the question, function objects can be mutated as a proxy: so carry on, flavoring as desired.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! It is very unfortunate that this cannot be done as of ES10, but this will suffice.
0

So it might help to give a more concrete example of what you want, but here's a few options that can pretty much replicate, and more, the things you have mentioned.

This is like your first example. I'm guessing this isn't what you actually want. Notice foo and bar are static.

const func = Object.assign( function(in){ console.log(in, func.foo, func.bar) }, { foo: x, bar: y } );

This one is probably closer to what you'd see in a class with () overloaded

const func = ( function(in){ console.log(in, this.foo, this.bar) } ).bind({ foo: x, bar: y });

Or something like this:

o = o => o['()'].bind(o)
const func = o({
  "()": function(x){ console.log(x, this.foo, this.bar) },
  foo: 1,
  bar: 2
});

Takes the property value of '()', and binds this to the object. You also use Object.assign to copy the properties on to the function.

Other way of expression

const func = (x,y) => ({
  foo: x, bar: y,
  plusone: () => func(x+1,y+1)
  showfoo() { return this.foo }
})

2 Comments

So, I actually planned on using something more like this: const func = Object.seal(Object.assign((...) => { ... }, { foo: x, bar: y })); I prefer Object.assign if I can use it, but I've been told by JavaScript beginners and legacy coders that it makes code "less readable", I discarded their comments. I'm here to ask because my end goal was making a class out of this. If the constructor has a return, then the properties are all replaced with the return value. Do you have any ideas on how this might be achieved? I guess a wrapper function could work.
do you mean extending the prototype, so new instances will "inherit" the properties added? a code example with before and after would help to get across what you need
0

You could do stuff like this, for example from within an outer IIFE function, returning different types of object formatted data. The IIFE can be passed as a parameter to another function in a modular script file, where controller's return data can be reached with dot notation controllerAsParameter.dostuff or controllerAsParameter.getNumbers.percentage.

Is my interpretation correct, based on your last example, that you're after something like this?

const controller = (function() {

    return {
        doStuff: function() {
           data.everything.forEach(function(foo) {
               foo.calculateStuff(data.totals.bar);
        });
    },

    getNumbers: function() {
        return {
            abc: data.abc,
            totalDef: data.totals.def,
            totalGhi: data.totals.ghi,
            percentage: data.percentage
        }
      }
   }
})();

2 Comments

I'm aiming to still be able to do controller() which you're example disallows.
@JadenGarcia You could pass the const controller into another function as an argument, and then access its return objects there. E.g. init( controller ) where the function itself is something like let init = ( ctrl ) => { }. Then inside init() you can access controller.doStuff with ctrl.doStuff. Can that method work?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.