[[Call]] vs. [[Construct]] using symbols

Herby Vojčík herby at mailbox.sk
Sat Oct 6 08:14:46 PDT 2012



David Bruant wrote:
 > 2012/10/3 Herby Vojčík <herby at mailbox.sk <mailto:herby at mailbox.sk>>
 >
 >     Hello,
 >
 >     now that we have symbols (and use some of them language-wise, like
 >     @iterator or proposed @toStringTag), I'd say we can probably dissect
 >     [[Call]] and [[Construct]] semantics fairly easily. Assuming there
 >     are global constant symbols @construct and @call,
 >
 > And I assume being able to arbitrarily change the [[Call]] and
 > [[Construct]] of a function at any time?
 >
 >     for min-max classes the issue is very simple:
 >
 >     class Foo {
 >              @construct(bar) {
 >                      this.bar = bar;
 >              }
 >              @call() {
 >                      // do something else
 >              }
 >     }
 >
 > I'm not sure this is appropriate for min-max classes. These are not so
 > much private properties as they are internal properties.

They are not private symbols, they are unique symbols. Like @iterator. 
And they are not used to define properties (see below).

 >     I'd propose the above as the minimal proposal for [[Call]] and
 >     [[Construct]] separation (even when it only works for classes; and
 >     so they can be abused to create function with [[Call]] and
 >     [[Construct]] separated).
 >     Implementation would be to create Foo such that it chooses one or
 >     the other based on whether [[Call]] or [[Construct]] is invoked.
 >
 > So I guess I misanderstand. Do you want @call and @construct to be
 > properties of instances of the constructor?

I want them to be properties of nothing. `constructor` is also just a 
convention (stemming from the fact that, in fact, property named 
constructor is created in the prototype in case of plain constructor 
function and holds a pointer to the constructor function).

I want the @construct and @call symbols to be used as a convention to 
specify [[Construction]] and [[Call]] behaviour for the class.

Some sensible defaults being applied when only one is present, like 
[[Construct]] will reuse @call (in [[Construct]] way) if only @call is 
present, and [[Call]] will throw is only @construct is present (it is a 
class, after all).

But otherwise, they should only work as convention names and the 
resulting (class? constructor function?) created so that it has 
appropriate [[Construct]] and [[Call]] behaviour.

 >     It could go further, like this:
 >
 >     var f = { @construct() {console.log(1)}, @call() {console.log(2)} };
 >     f(); // logs 2
 >     new f; // logs 1
 >
 > var f  = new Proxy(function(){console.log(1)}, {construct:
 > function(){console.log(2)}});
 > Arguably, this is as readable (and efficient) and yields the same 
result.

Hm, interesting, if it is this short, it is hard to beat. It is a proxy, 
though, is it really efficient? But yes, it is simple.

 > David
Herby


More information about the es-discuss mailing list