Promise() vs. new Promise()

Andrea Giammarchi andrea.giammarchi at gmail.com
Wed Aug 20 19:30:43 PDT 2014


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: brendan at mozilla.org
Cc: es-discuss at 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 at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


More information about the es-discuss mailing list