# Symbol.callable for callable object

**URL:** <https://es.discourse.group/t/symbol-callable-for-callable-object/2217>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [November 17, 2024, 3:23pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217 "2024-11-17T15:23:10Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![AaylaSecura](https://avatars.discourse-cdn.com/v4/letter/a/ecccb3/32.png) [@AaylaSecura](https://es.discourse.group/u/AaylaSecura)\
**Post date:** [November 17, 2024, 3:23pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/1 "2024-11-17T15:23:10Z")

</div>

Erm, I would be veery surprised if this hasn't already been proposed (or maybe it's that dumb of an idea 🙃), but I couldn't find any discussion on this.

I'd like to have a `Symbol.callable` to make an object "callable", similar to how `Symbol.iterator` makes it iterable. For example:

```javascript
class Foo {
    someProp = 'foo';
    // some other fields and methods...
    constructor(x = 0) {
        this[Symbol.callable] = (y) => x + y;
    } 
}

const f = new Foo(1);
f(2); // -> 3

```

Currently, the only way I've seen to achieve something like this is to assign properties to a function, like so:

```javascript
const newFoo = (x = 0) => {
    const func = (y) => x + y;
    func.someProp = 'foo';
    return func;
}
const f = newFoo(1);

```

I think this is kind of ugly/weird and it's awkward if you want to make it behave like an actual instance of an object (with its prototype pointing to `Foo`). In the latter case, you'd need to do that:

```javascript
function Foo (x = 0) {
    const func = (y) => x + y;
    func.someProp = 'foo';
    return Object.setPrototypeOf(func, Foo.prototype);
}
const f = new Foo(1);

```

which is even weirder to me and the object doesn't get proper annotation in the console (it's displayed as a function, rather than a `Foo` object with `someMethod`).

Please let me know if this has been discussed and what was the discussion.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [November 17, 2024, 3:39pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/2 "2024-11-17T15:39:02Z")

</div>

It’s been proposed for classes, but i doubt it would ever work as a generic protocol because it would likely slow down calling behavior for all functions.

More important than the suggested solution, though, is the problem - what problem are you solving?

---

<div class="post-metadata">

**Author:** ![AaylaSecura](https://avatars.discourse-cdn.com/v4/letter/a/ecccb3/32.png) [@AaylaSecura](https://es.discourse.group/u/AaylaSecura)\
**Post date:** [November 17, 2024, 4:07pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/3 "2024-11-17T16:07:28Z")

</div>

Thanks for replying @ljharb . Do you know what the consensus was on the proposal for classes, do you have a link?

There's nothing more to the problem, than what I stated. I would like to create a custom object that can be invoked like a function but also have other properties/methods and a custom prototype (that can be checked with `instanceof`). The example I should using a function, assigning properties and a prototype to it, does what I want, but I find it very unappealing and against the class design.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [November 17, 2024, 4:18pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/4 "2024-11-17T16:18:29Z")

</div>

Why would you like to create that? Wouldn’t that be surprising to users when nothing else in the language has that interface?

---

<div class="post-metadata">

**Author:** ![AaylaSecura](https://avatars.discourse-cdn.com/v4/letter/a/ecccb3/32.png) [@AaylaSecura](https://es.discourse.group/u/AaylaSecura)\
**Post date:** [November 17, 2024, 4:34pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/5 "2024-11-17T16:34:18Z")

</div>

I guess what I'm suggesting is that the language implements that interface.

As long as it's documented, I don't see why it would be surprising to users.

A custom callable can be passed to external methods or used by users that expect a function but that same object can be passed to methods that are aware of this type and can handle it in a different way. I hope this makes sense.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [November 17, 2024, 8:50pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/6 "2024-11-17T20:50:42Z")

</div>

A real world example would be the Mocha test framework. They provide an it() and describe() function to define tests, but you can also do things such as it.only() to make it be the only test that gets ran. I've done similar stuff in one of my own libraries, where the primary export was a template tag, and I chose to attach various helpers/tools as properties to that template tag.

I can't currently think of any real world examples where having a custom prototype to enable a working instanceof check is needed.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [November 18, 2024, 7:21am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/7 "2024-11-18T07:21:12Z")

</div>

Related thread: [Function object initializer](https://es.discourse.group/t/function-object-initializer/1886)

---

<div class="post-metadata">

**Author:** ![mhofman](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@mhofman](https://es.discourse.group/u/mhofman)\
**Post date:** [November 18, 2024, 7:29am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/8 "2024-11-18T07:29:57Z")

</div>

Callable is an intrinsic trait of objects, and I don't believe it should become a protocol. Since you can already fairly easily create callable objects and add properties, I don't think it's really needed either. For instanceof checks there's already a protocol for that to avoid having to update the proto of the callable. Outside of that and replicating class inheritance, the use cases for a different proto in callables are so unclear that relying on setPrototypeOf feels sufficient for them.

Edit: that said I could be convinced by a declarative way of declaring custom callable objects like object literals.

---

<div class="post-metadata">

**Author:** ![AaylaSecura](https://avatars.discourse-cdn.com/v4/letter/a/ecccb3/32.png) [@AaylaSecura](https://es.discourse.group/u/AaylaSecura)\
**Post date:** [November 18, 2024, 7:36am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/9 "2024-11-18T07:36:13Z")

</div>

> [@mhofman](#):
>
> For instanceof checks there's already a protocol for that to avoid having to update the proto of the callable

Sorry, I didn't get that, how does one implement `instanceof` check without updating the proto of the callable?

---

<div class="post-metadata">

**Author:** ![mhofman](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@mhofman](https://es.discourse.group/u/mhofman)\
**Post date:** [November 18, 2024, 7:38am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/10 "2024-11-18T07:38:21Z")

</div>

Use [`Symbol.hasInstance`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance) on your "constructor"

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [November 18, 2024, 4:26pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/11 "2024-11-18T16:26:26Z")

</div>

I don't love Symbol.hasInstance. it just feels like a lie - claiming that an object is an instance of a value without there actually being a prototype in common. I would prefer mangling prototypes over using it.

Anyways, I am realizing a problem with a callable protocol - if you can make any object callable, it means functions such as .call() won't be directly available, which means you can't blindly pass callable objects into places that expect functions as parameters.

Perhaps some declarative approach, like you mentioned, where perhaps you can declare a function with custom properties using syntax would be better, but it feels like a hard sell - these kinds of things do appear in the wild, but they're not extremely common.

And, we sort of already have a declarative approach - we can do `{ __proto__ () { ... }, otherFn() { ... } }`.

---

<div class="post-metadata">

**Author:** ![Josh-Cena](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/josh-cena/32/1408_2.png) [@Josh-Cena](https://es.discourse.group/u/Josh-Cena)\
**Post date:** [November 18, 2024, 6:05pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/12 "2024-11-18T18:05:56Z")

</div>

> [@theScottyJam](#):
>
> And, we sort of already have a declarative approach - we can do `{ __proto__ () { ... }, otherFn() { ... } }`.

` __proto__ () {}` does not declare the prototype. The only way to declare a prototype is with ` __proto__ : ...`, so you probably want ` __proto__ : function () {}` instead.

Also, a callable prototype does not make the object itself callable; you need to actually declare it as a function to make it callable.

---

<div class="post-metadata">

**Author:** ![AaylaSecura](https://avatars.discourse-cdn.com/v4/letter/a/ecccb3/32.png) [@AaylaSecura](https://es.discourse.group/u/AaylaSecura)\
**Post date:** [November 19, 2024, 5:30am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/13 "2024-11-19T05:30:07Z")

</div>

> [@theScottyJam](#):
>
> if you can make any object callable, it means functions such as .call() won't be directly available

I would have thought that it's possible to implement this such that if we defined `Symbol.callable` on an object (and the value would obviously be a function), it would transparently proxy `.call`, `.bind` and `.apply` to that function as well. Is it not? I understand it may create a clash in case the object also defines those properties, but that's also the case when you use a plain function with custom properties (you can always override methods on `Function.prototype`.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [November 19, 2024, 7:01am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/14 "2024-11-19T07:01:53Z")

</div>

> [@Josh-Cena](#):
>
> ` __proto__ () {}` does not declare the prototype. The only way to declare a prototype is with ` __proto__ : ...`, so you probably want ` __proto__ : function () {}` instead.
> 
> Also, a callable prototype does not make the object itself callable; you need to actually declare it as a function to make it callable.

Huh, you're right. That first part seems really weird, I wonder what the rational is for having ` __proto__ () { ... }` syntax behave differently from ` __proto__ : function() { ... }`.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [November 19, 2024, 1:25pm UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/15 "2024-11-19T13:25:12Z")

</div>

> [@AaylaSecura](#):
>
> I would have thought that it's possible to implement this such that if we defined `Symbol.callable` on an object (and the value would obviously be a function), it would transparently proxy `.call`, `.bind` and `.apply`

Things like this add an overhead to the whole language. Now every property lookup needs to check if the prop is "call" and then also check for Symbol\_callable. This overhead applies both to the implementation and also when trying to reason about the language

---

<div class="post-metadata">

**Author:** ![mhofman](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@mhofman](https://es.discourse.group/u/mhofman)\
**Post date:** [November 20, 2024, 9:17am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/16 "2024-11-20T09:17:42Z")

</div>

Edit: short-hand function object declaration discussion moved to [Function object initializer - #15 by mhofman](https://es.discourse.group/t/function-object-initializer/1886/15)

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [November 21, 2024, 3:15am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/17 "2024-11-21T03:15:30Z")

</div>

> [@AaylaSecura](#):
>
> implement this such that if we defined `Symbol.callable` on an object (and the value would obviously be a function)

Wait, what is (obviously) a function under this proposal? Does that no longer mean the same as "callable object"? Otherwise we'd have to recursively check if `obj[Symbol.callable]` is an object with a `[Symbol.callable]` property and so on...

---

<div class="post-metadata">

**Author:** ![AaylaSecura](https://avatars.discourse-cdn.com/v4/letter/a/ecccb3/32.png) [@AaylaSecura](https://es.discourse.group/u/AaylaSecura)\
**Post date:** [November 21, 2024, 4:43am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/18 "2024-11-21T04:43:25Z")

</div>

Good catch on the language use. Yes, I meant that the value of `Symbol.callable` would itself be a callable. Under this proposal then whenever a non-native function object is invoked, then the `Symbol.callable` property would be checked and if not callable, then error is thrown. So yes, in theory it would naturally be recursive, but I don't think it will be an issue. It would be essentially the same as having a function invoke another function. It's possible to lead to infinite recursion but that's as a result of a wrong usage rather than a flow in the spec I think.

---

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [November 22, 2024, 12:47am UTC](https://es.discourse.group/t/symbol-callable-for-callable-object/2217/19 "2024-11-22T00:47:03Z")

</div>

This seems problematic for engines that have a lot of optimizations built around function calls. This effect can be achieved by constructing the object on an object of type `function`, such as

```js
const obj = () => {
    // This is the [callable] overload
}
obj.propA = 1
obj.propB = 2

```

or better yet

```js
const obj = Object.assign(() => {
    // This is the [callable] overload
}, {
    propA: 1,
    propB: 2
}

```

This way our javascript stays reasonably fast ;)
