domenic at domenicdenicola.com (2014-06-20T19:31:52.027Z)
There's a lot of subtle stuff going on with these compatibility cases and addressing them was something we needed to do to get consensus around supporting subclassing of Array. I don't think we want to mess them up simply to avoid spec. level use of IsConstructor. I really don't expect anybody to seriously try to self-host the compatibility aspects of those methods and there is little point in trying to do a ES5 level shim that includes that functionality because other aspects of of subclassing just won't work in ES5.
On Jun 12, 2014, at 8:06 AM, Domenic Denicola wrote: > I'd be most interested in seeing if we can remove IsConstructor entirely (except for uses where it's just a guard, implementing the semantics of `new` via IsConstructor -> [[Construct]] or throw). > > It seems like there's at least some movement toward removing it from `Array.of` and `Array.from`. All that remains is its use to preserve the `arrayInstance.constructor = undefined` backward-compatibility possibilities. My preference would be to see if we can get away with breaking that use case, and reintroduce it if that turns out not to be web-compatible. There's a lot of subtle stuff going on with these compatibility cases and addressing them was something we needed to do to get consensus around supporting subclassing of Array. I don't think we want to mess them up simply to avoid spec. level use of IsConstructor. I really don't expect anybody to seriously try to self-host the compatibility aspects of those methods and there is little point in trying to do a ES5 level shim that includes that functionality because other aspects of of subclassing just won't work in ES5. Allen > > ________________________________________ > From: Allen Wirfs-Brock <allen at wirfs-brock.com> > Sent: Thursday, June 12, 2014 10:59 > To: Jason Orendorff > Cc: Domenic Denicola; EcmaScript > Subject: Re: IsConstructor > > On Jun 12, 2014, at 5:36 AM, Jason Orendorff wrote: > >> On Wed, Jun 11, 2014 at 11:44 AM, Allen Wirfs-Brock >> <allen at wirfs-brock.com> wrote: >>> Array.from and Array.of have a non-throwing IsConstrutor test because they are designed to allow things like this: >>> >>> let of = Array.of; >>> of(1,2,3,4,5); //Equivalent to: Array.of(1,2,3,4,5) >>> >>> I don't recall why we provided that functionality. It doesn't seem to me like a pattern we should want to encourage. >> >> I think it was meant for functional programming; but FP is so poorly >> supported by the rest of the standard library that it's not useful by >> itself. >> >> Array.of could test 'if the this value is undefined' rather than using >> IsConstructor(). I like that. I can't put my finger on it, but I >> suspect people will try to treat Array.of as a standalone function and >> get the "undefined is not a constructor" error, and be baffled. > > The problem with the undefined test is that it doesn't work if somebody tries to attach such functions to a namespace object: > > let arraybuilder = {of: Array.of, from: array:Array.from}; > arraybuilder.of(1,2,3,4); > > or consider, at the global level: > var of = Array.of; > of(1,2,3); //works > this.of(1,2,3) //breaks > > That's essentially why we have the IsConstructor test. To distinguish between this values that are actual constructors that will be used to create the new collection and non-constructor objects that are just contains for the function. > >> >> Back to the topic, it seems weird to go out of our way to expose >> @@isRegExp and @@isConcatSpreadable and also go out of our way to hide >> IsConstructor(). I don't like "does this object conform to this >> protocol" tests, but they are a fact of life in real JS code. > > I think the @@is methods and isConstructor are different kinds of beasts. isConstructor wold be a very general predicate that queries a fundamental characteristic of the meta-object protocol. The @@is methods are local to the implementation of a specific abstraction and nobody really needs to know about them unless they are trying to extend that abstraction. > > I'm not really opposed to an isConstructor predicate, I'm just pushing back to see if it is something that really needs to be exposed. If we have it, I think we probably should also have a isCallable predicate and I'd hand both of them off of Function. IE: > > Functiuon.isCallable(value) > Function.isConstructor(value) //or maybe it should be Function.isNewable ? > > Allen > >