Why can't objects be callable?

David Bruant bruant.d at gmail.com
Tue Mar 6 23:58:48 PST 2012


Le 07/03/2012 02:10, Brandon Benvie a écrit :
> I start this coming from the standpoint of an honest question that I
> don't know the answer to: is there a specific reason that objects
> can't be callable in js? Aside from the "that's just how the language
> is" answer, I was wondering if there's some other computer sciency or
> performance reason for the restriction.
One further detailled explanation of "that's just how the language work"
would be that a JavaScript invariant is that a value has a stable result
to "typeof". So it's impossible to change a non-callable object into a
callable object without breaking this invariant (as stated by ES5, a
callable object has "function" for it's typeof value while non-callable
objects have "object").

Besides this, I don't see a restriction on why you couldn't just use
functions each time you need an object.



> I've had this question a number of times but the most recent spart was
> seeing this from Allen Wirfs-Brock:
>
>>  //define a non constructible superclass that provides some Smalltalk-like conventions
>>  const AbstractClass = Function.prototype <| {
>>    subclassResponsibility() {throw new Error(this.name+" did not implemented an abstract method")},
>>    shouldNotImplement() {throw new Error(this.name+" should not implemented by "+this.name)},
>>    name: "AbstractClass",
>>    prototype: Object.prototype <|{
>>      get class() {return this.constructor},
>>      error(message) {throw new Error(message)},
>>      subclassResponsibility() {return this.class.subclassResponsibility()},
>>      shouldNotImplement() {return this.class.shouldNotImplement()},
>>      errorSubscriptBounds(index) {this.error("subscript is out of bounds: "+index)}
>>    }
>>  };
> As it is currently, the behavior of a function is that it defaults to
> be a `constructor-like`. It has a prototype that it bestows upon
> objects JS tells it to create, and it's not even possible for it to
> have no prototype property. I would imagine a callable object is more
> like a non-constructor function (something like isNaN) or, currently,
> it's essentially the same as doing `object.valueOf()`. In fact there's
> nothing stopping one from making every single object they use (aside
> from an array) callable simply by starting with a function literal and
> assigning its __proto__.
However, you do not need to use functions as constructors.
I wish block lambda [1] to be adopted for ES6. I think they would fit
your vision of functions, because it certainly wouldn't make sense to
construct with them and they would certainly have no use of a
'prototype' property.

Hopefully, it will be possible to combine block-lambda with the <|
operator to create callable objects with arbitrary prototype.

> (...)
> Partilly this is resolved with ES6, as is the arraylikes problem.
Indeed. All the "change the prototype at object creation time" was the
rational behind the <| operator (and as you note, it will work for
arrays, and functions and most things)

David

[1] http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival


More information about the es-discuss mailing list