Determining if an object can be constructed

Andrea Giammarchi andrea.giammarchi at gmail.com
Tue Jan 24 18:20:45 UTC 2017


as Claude already mentioned, that ain't going to work on Firefox due
following bug:
https://bugzilla.mozilla.org/show_bug.cgi?id=1216630

On Tue, Jan 24, 2017 at 6:12 PM, Isiah Meadows <isiahmeadows at gmail.com>
wrote:

> To clarify, I'm wanting to know if it's a callable that isn't a class.
> Technically, I could use `Function.prototype.toString` for most
> practical purposes of mine, but that'd be super slow (I'd need it in a
> warm loop), and wouldn't catch native construct-only classes like `Map`
> and `Set` (which are still `typeof f === "function"`).
>
> ```js
> var funcToString = Function.prototype.toString
>
> function isCallable(f) {
>     return typeof f === "function" &&
>         /^\s*class(\s*\{|\s+[^(])/.test(funcToString.call(f))
> }
> ```
> -----
>
> Isiah Meadows
> me at isiahmeadows.com
>
>
> On Mon, Jan 23, 2017 at 1:49 PM, Jordan Harband <ljharb at gmail.com> wrote:
> > Unfortunately, the only practical way to know that without risking side
> > effects is to read the human-produced documentation on the function, or
> to
> > have a human read the code.
> >
> > On Mon, Jan 23, 2017 at 8:19 AM, Isiah Meadows <isiahmeadows at gmail.com>
> > wrote:
> >>
> >> I'll point out that all I need is some way to detect anything that is
> >> callable except for classes. Basically, anything that has a `[[Call]]`
> that
> >> doesn't throw unconditionally without entering a different scope (like
> >> classes, but not %ThrowTypeError%).
> >>
> >> And to clarify, these would both be included per above, since it does
> >> enter a different scope:
> >>
> >> ```js
> >> // New language scope
> >> function foo() {
> >>   throw new TypeError()
> >> }
> >>
> >> // New native scope (%ThrowTypeError%)
> >> "use strict"
> >> var foo = Object.getOwnPropertyDescriptor(
> >>   arguments, "callee"
> >> ).get
> >> ```
> >>
> >> `Reflect.isConstructor` isn't sufficient for my needs, since it would
> >> still consider the first `foo` above to be a constructor.
> >>
> >>
> >> On Sat, Jan 21, 2017, 01:14 Jordan Harband <ljharb at gmail.com> wrote:
> >>>
> >>> 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
> >>>
> >>>
> >>> _______________________________________________
> >>> es-discuss mailing list
> >>> es-discuss at mozilla.org
> >>> https://mail.mozilla.org/listinfo/es-discuss
> >
> >
> _______________________________________________
> 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/20170124/bffcf0e1/attachment-0001.html>


More information about the es-discuss mailing list