Determine if a value is Callable/Constructible

Caitlin Potter caitpotter88 at gmail.com
Mon Mar 30 15:38:03 UTC 2015


> If you made them non-callable by not implementing [[Call]], then typeof would no longer return "function", which would be ... O_o.


s/Object (implements [[Call]]) |	“function” /Object (implements [[Call]] or [[FunctionKind]] is classConstructor) |	“function”/g

Problem solved!

I jest — but making a constructor identifiable as a function while still noting that it’s not “really” callable is certainly possible


> On Mar 30, 2015, at 11:27 AM, Domenic Denicola <d at domenic.me> wrote:
> 
> If you made them non-callable by not implementing [[Call]], then typeof would no longer return "function", which would be ... O_o.
> 
>> -----Original Message-----
>> From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of
>> Caitlin Potter
>> Sent: Monday, March 30, 2015 11:25
>> To: Yehuda Katz
>> Cc: es-discuss at mozilla.org
>> Subject: Re: Determine if a value is Callable/Constructible
>> 
>>>> But in either case, these (IsCallable / IsConstructor) are pretty basic
>> qualities of objects that a Reflection* api ought to be able to read into, imho.
>>> 
>>> What Allen is saying is that the implementation of "throw if
>>> constructor" doesn't work by not implementing [[Call]], but rather by
>> implementing [[Call]] to throw, so those reflective APIs would say the wrong
>> thing, and that this is observable via proxies.
>> 
>> It’s a fair point, constructors do have a [[Call]] internal method — there’s no
>> reason this needs to be described this way though. Instead of the extra step
>> for classConstructors in 9.2.1, class constructors could just as easily not have a
>> [[Call]] method at all (by default). I guess what I’m getting at is, right now
>> they aren’t “really” callable, it’s just that the way their non-callable-ness is
>> expressed makes them appear callable (which probably should not be the
>> case). Since they’re intrinsically not callable (currently), they shouldn’t be
>> treated as callable.
>> 
>> What Domenic is saying later on makes sense, the magic “call-code” method
>> (should it ever exist) shouldn’t be a property of the class prototype, so a
>> special syntactic form would work better (but also be kind of awful, too).
>> 
>>> 
>>> Allen, can you say more about why you spec'ed it that way?
>>> 
>>> 
>>>> 
>>>> 
>>>>> On Mar 29, 2015, at 11:51 PM, Caitlin Potter <caitpotter88 at gmail.com>
>> wrote:
>>>>> 
>>>>> ...
>>>>> 
>>>>> Reflect.isConstructor(fn) -> true if Class constructor, generator,
>>>>> or legacy (and non-builtin) function syntactic form
>>>>> Reflect.isCallable(fn) -> true for pretty much any function, except
>>>>> for class constructors and a few builtins
>>>> 
>>>> I’ve already seen another situation (node’s Buffer) where code could be
>> simplified by using a ES6 class definition but where that is prevented because
>> a class constructor throws when called.
>>>> 
>>>> Just to clarify something.  Class constructors actually are “callable”.  You
>> can observe this by the fact that Proxy allows you to install an “apply” handler
>> (the reification of the [[[Call]] internal method) on a class constructor.   The
>> the fact that an object can be [[Call]]’ed is already reflected  by the typeof
>> operator.  Class constructors throw when called because at the last minute
>> we choose to make their [[Call]] do an explicit throw not because they aren’t
>> callable.
>>>> 
>>>> There is no intrinsic reason why we needed to mandate that class
>> constructors should throw when called.  We even provided a simple and
>> straight forward way (new.target===undefined) that a ES constructor body
>> can use to determine whether it was called or new’ed.
>>>> 
>>>> I think we should just drop that throws when called feature of class
>> constructors..
>>>> 
>>>> (The restriction was added to future proof for the possibility of
>>>> inventing some other way to provide a class with distinct new/call
>>>> behavior. I don’t think we need nor can afford to wait for the
>>>> invention of a new mechanism which will inevitably be more complex
>>>> than new.target, which we already have.)
>>>> 
>>>> Allen
>>>> 
>>>> 
>>> 
>>> _______________________________________________
>>> 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



More information about the es-discuss mailing list