Reflect.hasOwn

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

Reflect.hasOwn

Maël Nison
Previous thread (2 years ago) here: https://esdiscuss.org/topic/reflect-hasown

It is still incredibly common to check if an object contains a key using:

    if (Object.prototype.hasOwnProperty.call(myObject, key))

This syntax is quite verbose, and doesn't really make sense in the first place. As someone said in the previous thread, hasOwnProperty should have never been added to the Object prototype.

According to the discussion, Reflect.hasOwn has been thrown away in order to keep the Reflect API simple, arguing that such a method could easily be replaced by Reflect.getOwnPropertyDescriptor anyway. While this is certainly true, the situation isn't without parallel with Array.prototype.includes, which has been added as least in part in order to help conveying a semantic meaning in the source code.

Since the usage hasn't decreased, what would you think about reconsidering Reflect.hasOwn for adoption?

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

RE: Reflect.hasOwn

Domenic Denicola
Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. http://www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the `in` operator works fine and there's no need for hasOwnProperty incantations.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Reflect.hasOwn

Maël Nison
JSON.parse() and object literals are big sources of objects-as-maps. In both of these cases, using the `in` operator won't give the right answer.

Le mar. 6 sept. 2016 à 22:11, Domenic Denicola <[hidden email]> a écrit :
Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. http://www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the `in` operator works fine and there's no need for hasOwnProperty incantations.

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

Re: Reflect.hasOwn

Isiah Meadows-2

I'll admit I use them partially out of laziness and partially because engines already optimize for this much better than with actual maps (only string keys). I frequently alias `const hasOwn = Object.prototype.hasOwnProperty`, so this wouldn't do much for me other than saving a declaration in each file I use it. Honestly, though, I feel it was a design flaw from the start to be on the prototype, but we can't just time travel and fix it.


On Tue, Sep 6, 2016, 16:42 Maël Nison <[hidden email]> wrote:
JSON.parse() and object literals are big sources of objects-as-maps. In both of these cases, using the `in` operator won't give the right answer.

Le mar. 6 sept. 2016 à 22:11, Domenic Denicola <[hidden email]> a écrit :
Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. http://www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the `in` operator works fine and there's no need for hasOwnProperty incantations.
_______________________________________________
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
Reply | Threaded
Open this post in threaded view
|

Re: Reflect.hasOwn

Maël Nison
Removing hasOwnProperty from Object.prototype would break a lot of code, so it's not even an option, but we could at least add Object.hasOwn, since Reflect apparently isn't the right place for this (it's a shame, it would mirror nicely with Reflect.ownKeys).

Doing this would improve a bit the clarity of new codes, and could prevent silly mistakes, the kind we all hate to debug (I've been unable to find a reliable tool that could search for exact matches in a large number of source codes, but I feel like forgetting the .call probably happens every once in a while).

Le mer. 7 sept. 2016 à 06:08, Isiah Meadows <[hidden email]> a écrit :

I'll admit I use them partially out of laziness and partially because engines already optimize for this much better than with actual maps (only string keys). I frequently alias `const hasOwn = Object.prototype.hasOwnProperty`, so this wouldn't do much for me other than saving a declaration in each file I use it. Honestly, though, I feel it was a design flaw from the start to be on the prototype, but we can't just time travel and fix it.


On Tue, Sep 6, 2016, 16:42 Maël Nison <[hidden email]> wrote:
JSON.parse() and object literals are big sources of objects-as-maps. In both of these cases, using the `in` operator won't give the right answer.

Le mar. 6 sept. 2016 à 22:11, Domenic Denicola <[hidden email]> a écrit :
Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. http://www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the `in` operator works fine and there's no need for hasOwnProperty incantations.
_______________________________________________
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
Reply | Threaded
Open this post in threaded view
|

Re: Reflect.hasOwn

Andrea Giammarchi-2
Just my 2 cents.

The tiniest JS utility I know [1] solves verbosity and freeze the method so it's also safe.

```js
// meet callerOf
function callerOf(c) {return c.call.bind(c)}

// how to use it
const hasOwn = callerOf({}.hasOwnProperty);

hasOwn({key: 'value'}, 'key'); // true
hasOwn({value: 'key'}, 'key'); // false
```

However, since functions also inherit from `Object.prototype`, I usually write this shortcut to semantically reach the `Object.prototype.hasOwnProperty` method, avoiding the need of the `callerOf` utility:

```js
// assign it once per module/scope
var hOP = Object.hasOwnProperty;

// whenever is needed
hOP.call({key: 'value'}, 'key'); // true
hOP.call({value: 'key'}, 'key'); // false
```

Beside the top level copy&paste operation to define `hOP`, writing `hOP.call(o,k)` is less verbose than `Reflect.hasOwn(o,k)` and strawberry on top, there's nothing else to explain for something that has been misunderstood for a very long time ( `hasOwnProperty` through `Object.prototype` vs `in` )

Best Regards





On Wed, Sep 7, 2016 at 9:34 AM, Maël Nison <[hidden email]> wrote:
Removing hasOwnProperty from Object.prototype would break a lot of code, so it's not even an option, but we could at least add Object.hasOwn, since Reflect apparently isn't the right place for this (it's a shame, it would mirror nicely with Reflect.ownKeys).

Doing this would improve a bit the clarity of new codes, and could prevent silly mistakes, the kind we all hate to debug (I've been unable to find a reliable tool that could search for exact matches in a large number of source codes, but I feel like forgetting the .call probably happens every once in a while).

Le mer. 7 sept. 2016 à 06:08, Isiah Meadows <[hidden email]> a écrit :

I'll admit I use them partially out of laziness and partially because engines already optimize for this much better than with actual maps (only string keys). I frequently alias `const hasOwn = Object.prototype.hasOwnProperty`, so this wouldn't do much for me other than saving a declaration in each file I use it. Honestly, though, I feel it was a design flaw from the start to be on the prototype, but we can't just time travel and fix it.


On Tue, Sep 6, 2016, 16:42 Maël Nison <[hidden email]> wrote:
JSON.parse() and object literals are big sources of objects-as-maps. In both of these cases, using the `in` operator won't give the right answer.

Le mar. 6 sept. 2016 à 22:11, Domenic Denicola <[hidden email]> a écrit :
Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. http://www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the `in` operator works fine and there's no need for hasOwnProperty incantations.
_______________________________________________
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



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

Re: Reflect.hasOwn

Caitlin Potter
In reply to this post by Domenic Denicola
>
> On Sep 6, 2016, at 4:10 PM, Domenic Denicola <[hidden email]> wrote:
>
> Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

I generally disagree with the idea that this doesn’t belong in “Reflect” because it’s not an MOP operation. There are three reasons for this.

1) only spec editors care about whether an operation is MOP or not. JS authors are concerned with operations and algorithms that are helpful to their work, not whether it’s written as [[Op]]() vs Op(). To a JS author, HasOwnProperty() is just as valid of a reflection mechanism as [[HasProperty]]().

2) Given what was said above about hasOwn() being a valid and useful reflection mechanism, and as you’ve mentioned, the “Reflect” namespace indicates that it performs reflection tasks, not that it lets you perform spec internal MOP operations.

3) Even if Reflect were exclusively for MOP operations, it tends to add extra steps which are not part of the MOP operation. These can make the methods more useful for JS consumers, or they can be convenience mechanisms, but either way, it’s not a 1:1 mapping to MOP operations.

I think it belongs in Reflect, as it’s a reflection capability, the MOP status is a moot point (and it’s just a thin wrapper around [[GetOwnProperty]] anyways), and changing Reflect is less likely to break content than changing Object.

In the meantime, `var hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty)` will continue to be a useful workaround for people.


> A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. http://www.2ality.com/2012/11/proto-breaks-webapps.html.
>
> If you are using objects-as-maps safely, you’d use Object.create(null), in which case the `in` operator works fine and there's no need for hasOwnProperty incantations.
> _______________________________________________
> 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

signature.asc (859 bytes) Download Attachment