I like the `Function.prototype.new` hint but unless it's an implicitly self bound method you still cannot easily pass it around as callback for a map without binding it all over.
`arr.map(MyClass.new)` without needing to explicitly bind it each time is needed/used would be an exception, but probably a good one. Regards Sent from my Windows Phone From: Allen Wirfs-Brock Sent: 8/21/2014 1:19 To: bren...@mozilla.org Cc: es-discuss@mozilla.org Subject: Re: Promise() vs. new Promise() On Aug 20, 2014, at 1:11 PM, Brendan Eich wrote: > Alex Kocharin wrote: >> I mean, not using `new`. JS is a functional language after all, and having a >> function that can't be called as a function is weird. > > Gotcha, and my point was not to mandate `new`, just allow it. I thought we > relaxed things so `new` was optional if there was no issue leaving it out: > > http://esdiscuss.org/topic/make-class-constructors-work-with-call-too > > But that was a while ago. > >> If constructor supports calling it without new, I can pass it around as a >> function, do this for example: >> >> ``` >>> > ['foo', 'bar'].map(Error) >> [ [Error: foo], [Error: bar] ] >> ``` >> >> With mandatory `new` this would be much less elegant. > > Agreed, mandating `new` where there's no issue (legacy, e.g., Date; or > other?) would be Bad(tm). > >> I was about to construct realistically-looking chain with [fn1, fn2, >> fn3].map(Promise).forEach(addThenHandler), but FF already seem to throw on >> it.:( > > Hrm. We've talked about this several times at TC39 meetings and the consensus has always been to not conflate the meaning of new C() and C() for new built-in constructors. The problem is that is difficult to correctly code (in ES code) a constructor function that has this behavior. Even assuming there is a way to reliably determined if you were called with or without `new` you still need to have to separate logic paths for the two cases and there are other subclassing issues (more below). For these reasons, we should expect that most constructors defined using `class` will require use of `new` to instantiate them. If as matter of principle, we shouldn't be specifying built-ins that do things in a way that is difficult to reproduce in ES code and we shouldn't be encouraging usage patterns that confuse people or are error prone to implement. If you want a purely functional way to do instantiation, then I suggest adding a `new` method to Function.prototype: ` Function.prototype = function new(...args) {return new this(...args); ` Back to subclassing, assume that Map was implemented in ES, something like this: ( **called-via-new** is a placeholder for new syntax) ` class Map { constructor(...args) { if (! **called-via-new**) return new Map(...args); // initialize this using args } //methods } //then the following do the same thing: var m = Map(); var m = new Map; ` You might then, reasonably expect to code ` class ExtendedMap extends Map { additionalMethod() {} } ` but if you do, you will discover: ` var m = ExtendedMap(); //actually creates an instance of Map var m = new ExtendedMap; //actually creates an instance of ExtendedMap; ` the problem is that the Map constructor explicitly references `Map` rather than the actually invoked constructor and there is no good may to determine what the actual constructor was. So to make the subclass work correctly you have to remember to code the subclass as: ` class ExtendedMap extends Map { constructor(...args) { if (! **called-via-new**) return new ExtendedMap(...args); return new super(...args); } additionalMethod() {} } ` and repeat a pattern like this in every other subclass you write. Much better to just avoid this sort ot two-faced constructors. Alen _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss