Determining if an object can be constructed

Jordan Harband ljharb at gmail.com
Sat Jan 21 06:13:19 UTC 2017


The reality here is that we're all playing around what the definition of
"constructor" and "callable" mean.

In the spec, "constructors" are defined as having a `[[Construct]]`
internal slot; something is "callable" if it has a `[[Call]]` internal
slot. By that definition (https://tc39.github.io/ecma262/#sec-isconstructor
and https://tc39.github.io/ecma262/#sec-iscallable), a `class` constructor
is indeed callable (because it's defined to have `[[Call]]` throw a
`TypeError`). Similarly, as defined in the spec, `typeof class Foo {}` is
"function" only because it has a `[[Call]]` internal slot (
https://tc39.github.io/ecma262/#table-35); if constructors lacked a
`[[Call]]` slot (such that `IsConstructor` returned `true` for them), then
`typeof someConstructor` would return "object".

Obviously the committee could have chosen to define these things
differently; but this is how things are defined.



I'm going to claim that conceptually - eg, to the majority of users -
something is a constructor when it's *intended* to be used with `new`. In
other words, "what it returns" isn't actually the point - if you're "meant"
to use it with `new`, it's a constructor, otherwise, it's a function - and
functions that work with both can be thought of as a dual
constructor/factory (the factory calls the constructor for you). However,
that conceptual definition is not one that can be programmatically
determined, because "programmer intention" in this regard simply isn't
inherently enshrined in an observable way, whether choosing `class` or
`function`.

Personally I think it would be wonderful to expose `IsConstructor`
(`IsCallable` is already exposed via `typeof` returning "function"), but I
feel quite confident that neither actually address any of the use cases in
this thread.

In addition, "safe to call" or "safe to use with `new`" all depends on your
definition of "safe", and it's clear from this thread that that does not
have a universally agreed-upon definition either.

It might be useful to distill things down to 1) concrete use cases for
calling or instantiating a function where you don't already know what it
does, and can't assert in your human documentation what you expect; 2) a
definition of "constructor", either a different one if you don't agree with
mine above, or if you do, a form of mine that can be programmatically
determined, and 3) a definition of "safe" which means more than "doesn't
throw an exception".

On Fri, Jan 20, 2017 at 6:52 PM, Scott Sauyet <scott at sauyet.com> wrote:

> Bradley Meck wrote:
> >> 1. every call to `new Foo(...args)` creates a distinct object not
> >> reference-equal to any other such call.
> >
> > Would this mean
> >
> > ```
> > function factory() { return []; }
> > ```
> >
> > would qualify as a constructor?
>
> I'm thinking of that as a necessary, but not a sufficient condition.
>
> If it fails that test it cannot be a constructor.  It's clear that
> there are other tests.  It's not clear to me what they are.
>
>   -- Scott
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170120/98f520cb/attachment-0001.html>


More information about the es-discuss mailing list