Constructors need to be able to recognize uninitalized instances(?)

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Constructors need to be able to recognize uninitalized instances(?)

Axel Rauschmayer
[Referring to Allen’s slides: http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013&cache=cache&media=meetings:subclassing_builtins.pdf ]

Is this really true?

I can see four ways of invoking a constructor function C:

1. As a function: C(...)
2. Via `new`: new C(...)
3. Via `call`: C.call(this, ...)
4. Via `super`, in a sub-instance, as a method (similar to #3): super.constructor(...)

C[@@create] is only invoked during #2 (by the `new` operator). Thus, the constructor’s role is always: set up an uninitialized instance. You could add a check against an instance being initialized twice, but that doesn’t seem to be what the slides are about.

The slides mention one use case: What if you want to have a function Foo that can be either called as a function or as a constructor? You can’t detect the difference if Foo is inside a namespace object. That is, you want to distinguish #1 from all others, but #1 could happen to a namespaced C. Observations:

– Does recognizing whether `this` is initialized really help here? Isn’t it more about checking whether `this` is an instance of C?

– I’ve always considered this to be more of an anti-pattern for non-builtin code. Thus, it seems useful to support a check, but only so that namespaced constructors can avoid accidentally polluting the namespace object.

– Won’t namespace objects go away with modules?

Thanks!

Axel

-- 
Dr. Axel Rauschmayer



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Constructors need to be able to recognize uninitalized instances(?)

Axel Rauschmayer
Thanks!

awbjs IOW, I’d write the check: if (typeof this !== "object" || !($fooBrand in this) || this[$fooBrand]) /*CAAF*/

perhaps:  if ( this ===null || typeof this !== "object" ||  this[$fooBrand]!==undefined) /*CAAF*/
if depends upon how the @@create method chooses to use as an "uninitialized" marker.  Setting the brand property value to undefined works in many cases.

The `this[$fooBrand]!==undefined` still looks wrong (it would be true for an uninitialized instance). How about the following?

    if ( this ===null || typeof this !== "object" ||  this[$fooBrand] !== false) /*CAAF*/

Then the last Or operand is true if either the instance has already been initialized or if `this` is an object that does not have a property whose key is $fooBrand (e.g. a namespace object). Interestingly, this expression is not the same as `! this[$fooBrand]`.

@awbjs On slide 22, wouldn’t you first call @@create (⇒this[$fooBrand]=false) and then execute the “constructor initialization case”?

Are you talking about for the CAAF case?   If you want factory function behavior I would code the then clause as: return new Foo();
or perhaps: return new this.constructor()
You could put in explicit calls to @@create but it probably better to let new do that part.

In the Rev 14 draft, most of the built-in constructors that have CAAF behavior use some variation of this pattern expressed in pseudo code.

I think the built-in support in slides 23 and 24 would be best, but TC39 doesn't really understand it yet. 

I’d prefer a dynamic solution, but don’t see one.

-- 
Dr. Axel Rauschmayer



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Constructors need to be able to recognize uninitalized instances(?)

Axel Rauschmayer
    if ( this ===null || typeof this !== "object" ||  this[$fooBrand] !== false) /*CAAF*/

Then the last Or operand is true if either the instance has already been initialized or if `this` is an object that does not have a property whose key is $fooBrand (e.g. a namespace object). Interestingly, this expression is not the same as `! this[$fooBrand]`.

Sorry, correction:
`this[$fooBrand] !== false` is not the same as `this[$fooBrand]`. The former is true for `undefined`, the latter isn’t. The following is more intention-revealing:

    if ( this ===null || typeof this !== "object" ||  this[$fooBrand] === undefined || this[$fooBrand]) /*CAAF*/


-- 
Dr. Axel Rauschmayer



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Constructors need to be able to recognize uninitalized instances(?)

Herby Vojčík
In reply to this post by Axel Rauschmayer
I think the idea of detecting if you have initialized or noninitialized
instance at runtime is very unhappy idea.

You know when it is called as an initializer (2, 4 below) and when not
(1 below). 3 below is legacy way of doing super - it can be simply replaced.

And there is also no breaking compatibility cost - so far, there was no
API to distinguish this; so once it is added, it can be safely specified
that "initializer" context is only 2 and 4.

Herby

Axel Rauschmayer wrote:

> [Referring to Allen’s slides:
> http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013&cache=cache&media=meetings:subclassing_builtins.pdf
> <http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013&cache=cache&media=meetings:subclassing_builtins.pdf>
> ]
>
> Is this really true?
>
> I can see four ways of invoking a constructor function C:
>
> 1. As a function: C(...)
> 2. Via `new`: new C(...)
> 3. Via `call`: C.call(this, ...)
> 4. Via `super`, in a sub-instance, as a method (similar to #3):
> super.constructor(...)
>
> C[@@create] is only invoked during #2 (by the `new` operator). Thus, the
> constructor’s role is always: set up an uninitialized instance. You
> could add a check against an instance being initialized twice, but that
> doesn’t seem to be what the slides are about.
>
> The slides mention one use case: What if you want to have a function Foo
> that can be either called as a function or as a constructor? You can’t
> detect the difference if Foo is inside a namespace object. That is, you
> want to distinguish #1 from all others, but #1 could happen to a
> namespaced C. Observations:
>
> – Does recognizing whether `this` is initialized really help here? Isn’t
> it more about checking whether `this` is an instance of C?
>
> – I’ve always considered this to be more of an anti-pattern for
> non-builtin code. Thus, it seems useful to support a check, but only so
> that namespaced constructors can avoid accidentally polluting the
> namespace object.
>
> – Won’t namespace objects go away with modules?
>
> Thanks!
>
> Axel
>
> --
> Dr. Axel Rauschmayer
> [hidden email] <mailto:[hidden email]>
>
> home: rauschma.de <http://rauschma.de>
> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
> blog: 2ality.com <http://2ality.com>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss