Proposal: Symbol.inObject well-known symbol to customize the "in" operator's behavior

Tom Barrasso tom at barrasso.me
Fri May 10 02:33:52 UTC 2019


`handler.has(target, key)` appears to be the most direct way to accomplish
this, although as mentioned in requires dealing with string parsing.
Here's a quick example I put together using `Proxy` to accomplish the
`range` function.

```js
function range(min, max) {
  return new Proxy(Object.create(null), {
    has (target, key) {
      return (Number(key) >= min && Number(key) <= max)
    }
  })
}
```

However, the same cannot be achieved easily for Strings. I consider using
Strings directly, but got a "Uncaught TypeError: Cannot create proxy with a
non-object as target or handler."
I also considered using template tags as well, but that seemed like more of
a novel hack and not advantageous compared to a simple function. This is
the best I could come up with.

```js
function q(str) {
  const S = class extends String{}
  return new Proxy(new S(str), {
    has (target, searchString) {
      return str.includes(searchString)
    }
  })
}
```

A class that extends String is sufficient where a String itself is not,
although this has ramifications elsewhere like being passed by reference,
not value, through functions.
Based on the stringification and inability to work with native object
prototype, I'm not fully convinced that `Proxy` is a complete substitute
for `Symbol.inObject`.

Tom

On Thu, May 9, 2019 at 7:20 PM Isiah Meadows <isiahmeadows at gmail.com> wrote:

> There's several ways proxies can change the result of `in`:
>
> - Directly via `handler.has(target, key)` (returns boolean)
> - Indirectly via `handler.getOwnPropertyDescriptor(target, key)` (returns
> existing descriptor or `undefined` if missing)
> - Indirectly via `handler.getPrototypeOf(target)' (returns relevant
> prototype)
>
> The proxy trap `has` is almost a direct substitute for your
> `Symbol.inObject` in most cases, provided you're okay with keys getting
> stringified.
>
> On Thu, May 9, 2019 at 17:17 Tom Barrasso <tom at barrasso.me> wrote:
>
>> Thanks interesting, I hadn’t realized it was possible to “trap” the in
>> operator using Proxy. I may be wrong, but I don’t think Proxy is capable of
>> operating on the prototype chain. Specifically, I don’t think you can
>> change the behavior of the in operator for all Strings (which I’m sure many
>> would prefer).
>>
>> If this Symbol were seriously considered I believe it would expand the
>> meaning of the in operator as you’re correct, this is definitely not it’s
>> current intention.
>>
>> Tom
>>
>> On Thu, May 9, 2019 at 4:39 PM Claude Pache <claude.pache at gmail.com>
>> wrote:
>>
>>>
>>>
>>> Le 9 mai 2019 à 20:52, Tom Barrasso <tom at barrasso.me> a écrit :
>>>
>>> Like Symbol.hasInstance but for the "in" operator.
>>> This symbol would work for both native and user-defined objects.
>>>
>>> **Example implementation** prototyping native object:
>>>
>>> ```js
>>> String.prototype[Symbol.inObject] =
>>>   function(searchString) {
>>>     return this.includes(searchString)
>>> }
>>> ```
>>>
>>>
>>> **Example implementation* *for user-defined object:
>>>
>>> ```js
>>> function range(min, max) => ({
>>>     [Symbol.inObject]: (prop) => {
>>>         return (prop >= min && prop <= max)
>>>     }
>>> })
>>> ```
>>>
>>>
>>> **Example usage**:
>>>
>>> ```js
>>> ("foo" in "food")    // true
>>> (14 in range(1, 25)) // true
>>> ```
>>>
>>>
>>> Those two examples seem to give to the `in` operator a meaning that it
>>> was not intended to have. The `in` operator is specifically meant to check
>>> whether a given property exists in a given object.
>>>
>>> Also, there already exists a way to customise the behaviour of the `in`
>>> operator, namely by using a Proxy.
>>>
>>> —Claude
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> --
> -----
>
> Isiah Meadows
> contact at isiahmeadows.com
> www.isiahmeadows.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20190509/4b7bd34f/attachment-0001.html>


More information about the es-discuss mailing list