new instantiation design alternatives

Claude Pache claude.pache at gmail.com
Fri Sep 12 04:22:08 PDT 2014



Le 12 sept. 2014 à 08:39, Jeff Morrison <lbljeffmo at gmail.com> a écrit :

> " If a constructor body contains an assignment of the form this = then automatic allocation is not performed and the constructor is expected to perform manual allocation."
> If I'm understanding this correctly, this means that snippet (A) would never have access to `this`, but snippet (B) would have an implicit `this` binding -- is that correct?
> 
> (A)
> ```
> class Foo extends Bar {
>   constructor() {
>     if (false) {
>       this = super();
>     }
>     this; // undefined
>   }
> }
> ```
> 
> (B)
> ```
> class Foo extends Bar {
>   constructor() {
>     // No call to `this =` present in the constructor 
>     this; // the automatically allocated object -- i.e. this !== undefined
>   }
> }
> ```
> 
> If this is the case, it occurs to me that it would raise issues for things like automated refactoring and/or dead code elimination (as a minifier might do).
> Normally a minifier (or even a human) would expect to be able to eliminate the entire conditional altogether if they were confident the condition never evaluated to true. But with this static pre-check acting as the indicator for whether automatic allocation/binding should happen, doing so would cause the constructor to act very unexpectedly differently in the two cases.
> 
> I wish I could suggest an alternative, but nothing comes to mind right now.
> 
> Thoughts?

So, let's explore how to cope with the design that consists to determine the automaticity of allocation/binding independently of the actual code of the constructor (as it was the case in my original design.) 

The rule must be the following one:

* For constructors in classes, automatic allocation occurs if and only if there is no `extends` clause.
* For constructors defined the ES1-5 way (outside classes), automatic allocation occurs.

That is satisfying for most cases while remaining backward compatible with ES1-5, but it is a priori problematic in the following situations, where one may want manual allocation whereas the rule mandates an automatic one.

(1) Base classes (i.e., classes without `extends` clause) that want manual allocation. The legacy possibility of returning an alien object from the constructor remains. Alternatively, the following hack is possible, provided that we accept `Function.prototype` as a constructor.

	class Base extends Function.prototype { /* ... */  } 

(IIUC, the prototype chain for both constructor and instances will be the same as without the `extends Function.prototype` clause.) If that situation occurs often, we might want to provide sugar around that.

(2) Constructors defined outside classes that want manual allocation of `this`. For these, I propose the following syntax:

	function Derived(a, b) extends Base { /* ... */ }

as an almost equivalent of:

	function Derived(a, b) { /* ... */ }
	Derived.__proto__ = Base
	Derived.prototype = { __proto__: Base.prototype || Object.prototype, constructor: Derived }

except that the automatic allocation of `this` does not occurs in the former case. Like constructors defined in classes, the `extends Function.prototype` trick is possible.

—Claude
	

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140912/d502eaa0/attachment-0001.html>


More information about the es-discuss mailing list