[[Call]] and [[Construct]]

# David-Sarah Hopwood (16 years ago)

Maciej Stachowiak wrote:

On Sep 27, 2009, at 11:14 AM, Brendan Eich wrote:

On Sep 27, 2009, at 10:41 AM, David-Sarah Hopwood wrote:

Brendan Eich wrote:

On Sep 26, 2009, at 6:08 PM, Maciej Stachowiak wrote:

This may provide a way to implement some of these behaviors in pure ECMAScript. The current proposal does allow [[Construct]] without [[Call]], but not [[Call]] and [[Construct]] that both exist but with different behavior.

Date needs the latter.

That can already be done in ES5. As I've previously suggested:

function Date(yearOrValue, month, date, hours, minutes, seconds, ms) { "use strict"; if (this === undefined) { return TimeToString(CurrentTime()); } // constructor behaviour ... }

Of course, a variation on "the idiom".

This is similar to what many implementations do too, rather than the implementation providing analogues of [[Call]] and [[Construct]] internal method on a non-function Date object. It works for Boolean, Number, String, and RegExp too.

But it is just a bit unsightly!

Will this do the right thing if you explicitly bind Date to a "this" value, for example, by calling it as window.Date(), or using call, apply, or function.bind, or by storing Date as the property of another random object?

Now that I think about it, probably not (it will attempt to set the [[Class]] of 'this' to "Date", which is unsafe). But the problem here isn't introduced by the fact that [[Call]] and [[Construct]] have different behaviour: none of the other built-in constructors can be safely expressed in ES5 for the same reason, regardless of their [[Call]] behaviour.

# Maciej Stachowiak (16 years ago)

+public-script-coord

On Sep 27, 2009, at 4:19 PM, David-Sarah Hopwood wrote:

Maciej Stachowiak wrote:

On Sep 27, 2009, at 11:14 AM, Brendan Eich wrote:

On Sep 27, 2009, at 10:41 AM, David-Sarah Hopwood wrote:

That can already be done in ES5. As I've previously suggested:

function Date(yearOrValue, month, date, hours, minutes, seconds,
ms) { "use strict"; if (this === undefined) { return TimeToString(CurrentTime()); } // constructor behaviour ... }

Of course, a variation on "the idiom".

This is similar to what many implementations do too, rather than the implementation providing analogues of [[Call]] and [[Construct]] internal method on a non-function Date object. It works for Boolean, Number, String, and RegExp too.

But it is just a bit unsightly!

Will this do the right thing if you explicitly bind Date to a "this" value, for example, by calling it as window.Date(), or using call, apply, or function.bind, or by storing Date as the property of
another random object?

Now that I think about it, probably not (it will attempt to set the [[Class]] of 'this' to "Date", which is unsafe). But the problem here isn't introduced by the fact that [[Call]] and [[Construct]] have different behaviour: none of the other built-in constructors can be safely expressed in ES5 for the same reason, regardless of their [[Call]] behaviour.

I believe the built-in constructors could be implemented correctly by
ignoring their "this" parameter and making a fresh object of the
appropriate type, rather than by modifying the [[Class]] of a presumed
"this" passed as part of construction. For any that have identical
[[Call]] and [[Construct]] behavior, it would then be fine to write it
as a function - either way it produces a new object and ignores
whatever may have been passed for "this". This is true for Array for
instance. (Object call and construct also look like they have the same
behavior, though written in two different ways for some reason.)

, Maciej