Allen Wirfs-Brock (2015-01-19T16:54:47.000Z)
On Jan 19, 2015, at 5:51 AM, Claude Pache wrote:

> 
>> Le 19 janv. 2015 à 11:58, Andreas Rossberg <rossberg at google.com> a écrit :
>> 
>> On 17 January 2015 at 19:14, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
>> On Jan 17, 2015, at 9:53 AM, Domenic Denicola wrote:
>> > On Jan 17, 2015, at 12:31, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
>> >>
>> >> If the enclosing function is invoked as a call expression the value of  `new.target` is null
>> >
>> > Just curious, why null instead of undefined?
>> 
>> null is used to indicate no [[Prototype]], so it seem to me to be a better match for this situation.
>> 
>> Wouldn't the fact that null is a quasi-legal prototype strongly speak for using undefined here? Otherwise, it seems you couldn't distinguish Call invocations from Construct invocations with a prototype that has actually been set to null (which I suppose is legal?).
>> 
>> (In terms of proper option/maybe types, this is yet another case of a None vs Some(None) distinction.)
>> 
>> /Andreas
>> 
> 
> `new.target` is a reference to the constructor, not the prototype, so the problem does not arise in practice.
> 
> But anyhow, I do think that `undefined` is semantically better here:
> 
> * `new.target === null` means: `new.target` has been set to "no object".
> * `new.target === undefined` means: `new.target` has not been set.

At the JS level, I don't actually think about `new.target` as something that is "settable". I think about it as an oracle that tells me about how this function was invoked.  null means it was invoked "as a function".  non-null means it was invoked as a constructor and the value is the object that `new` was applied to. 

> 
> When you execute a function body with the semantics of [[Construct]], the value of `new.target` is the original constructor on which `new` was applied. If it was possible to have the semantics of [[Construct]] with no original constructor, then `new.target` would be `null` (no-object).

But it isn't.  Reflect.construct ensures that an non-null value is passed to [[Construct]] as its second argument 
> 
> But when you execute a function body with the semantics of [[Call]], there is no notion of "original constructor", and `new.target` is left with no value, i.e. `undefined`.

I originally intended `new.target` to use `undefined` is the sentinel value to indicated "called as a function".  But as I wrote the spec. it felt better to use `null` in that role.  I think it's because using `null` seems more special.  `undefined` is used in so many places to indicated so many different things that it is hard to apply any generalized meaning to it.  On the other hand, `null` is used in only a few places in the ES spec. so its use seems to draw attention to the specialness of those situations.

But, I'd have no problem with changing back to `undefined` if there is a consensus in favor of that.

It really makes very little difference as `null` and `undefined` are both falsey values, so the preferred way to write a "called as a function" these should probably be:

`if (! new.target) ...`

Allen

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150119/e059e160/attachment.html>
d at domenic.me (2015-01-28T19:34:22.400Z)
On Jan 19, 2015, at 5:51 AM, Claude Pache wrote:

> But anyhow, I do think that `undefined` is semantically better here:
> 
> * `new.target === null` means: `new.target` has been set to "no object".
> * `new.target === undefined` means: `new.target` has not been set.

At the JS level, I don't actually think about `new.target` as something that is "settable". I think about it as an oracle that tells me about how this function was invoked.  null means it was invoked "as a function".  non-null means it was invoked as a constructor and the value is the object that `new` was applied to. 


> When you execute a function body with the semantics of [[Construct]], the value of `new.target` is the original constructor on which `new` was applied. If it was possible to have the semantics of [[Construct]] with no original constructor, then `new.target` would be `null` (no-object).

But it isn't.  Reflect.construct ensures that an non-null value is passed to [[Construct]] as its second argument 

> But when you execute a function body with the semantics of [[Call]], there is no notion of "original constructor", and `new.target` is left with no value, i.e. `undefined`.

I originally intended `new.target` to use `undefined` is the sentinel value to indicated "called as a function".  But as I wrote the spec. it felt better to use `null` in that role.  I think it's because using `null` seems more special.  `undefined` is used in so many places to indicated so many different things that it is hard to apply any generalized meaning to it.  On the other hand, `null` is used in only a few places in the ES spec. so its use seems to draw attention to the specialness of those situations.

But, I'd have no problem with changing back to `undefined` if there is a consensus in favor of that.

It really makes very little difference as `null` and `undefined` are both falsey values, so the preferred way to write a "called as a function" these should probably be:

```js
if (! new.target) ...
```
d at domenic.me (2015-01-28T19:34:12.854Z)
On Jan 19, 2015, at 5:51 AM, Claude Pache wrote:

> But anyhow, I do think that `undefined` is semantically better here:
> 
> * `new.target === null` means: `new.target` has been set to "no object".
> * `new.target === undefined` means: `new.target` has not been set.

At the JS level, I don't actually think about `new.target` as something that is "settable". I think about it as an oracle that tells me about how this function was invoked.  null means it was invoked "as a function".  non-null means it was invoked as a constructor and the value is the object that `new` was applied to. 


> When you execute a function body with the semantics of [[Construct]], the value of `new.target` is the original constructor on which `new` was applied. If it was possible to have the semantics of [[Construct]] with no original constructor, then `new.target` would be `null` (no-object).

But it isn't.  Reflect.construct ensures that an non-null value is passed to [[Construct]] as its second argument 

> But when you execute a function body with the semantics of [[Call]], there is no notion of "original constructor", and `new.target` is left with no value, i.e. `undefined`.

I originally intended `new.target` to use `undefined` is the sentinel value to indicated "called as a function".  But as I wrote the spec. it felt better to use `null` in that role.  I think it's because using `null` seems more special.  `undefined` is used in so many places to indicated so many different things that it is hard to apply any generalized meaning to it.  On the other hand, `null` is used in only a few places in the ES spec. so its use seems to draw attention to the specialness of those situations.

But, I'd have no problem with changing back to `undefined` if there is a consensus in favor of that.

It really makes very little difference as `null` and `undefined` are both falsey values, so the preferred way to write a "called as a function" these should probably be:

`if (! new.target) ...`