Small Proposal "!in"

# Tobias Buschor (6 years ago)

I dont like to write: if ( !('x' in obj) && !('y' in obj) ) { doit() }

I was even tempted to write it that way: if ('x' in obj || 'y' in obj) { } else { doit() }

What about a !in operator to write it like this? if ('x' !in obj && 'y' !in obj) { doit() }

# T.J. Crowder (6 years ago)

On Thu, Jun 28, 2018 at 5:14 PM, Tobias Buschor <tobias.buschor at shwups.ch>

wrote:

I dont like to write: if ( !('x' in obj) && !('y' in obj) ) { doit() }

I was even tempted to write it that way: if ('x' in obj || 'y' in obj) { } else { doit() }

There's

if (!('x' in obj  ||  'y' in obj)) {
     doit()
}

That said, I've wanted !in many a time, in a minor sort of way...

-- T.J. Crowder

# Guylian Cox (6 years ago)

I agree, it's very annoying to have to write it !(x in y). I've been wanting this operator for a very, very long time.

If there is interest for !in, I think !instanceof deserves to be included too.

Le jeu. 28 juin 2018 à 18:19, T.J. Crowder <tj.crowder at farsightsoftware.com>

a écrit :

# Cyril Auburtin (6 years ago)
if (!obj.x && !obj.y) {
     doit()
}

The cases where they are equal to 0, '', null, undefined shouldn't matter imo, if for example those x and y are numbers, they would be defined, defaulted to 0, and you would test for !== 0 rather if needed

Le jeu. 28 juin 2018 à 18:31, Guylian Cox <guyliancox at gmail.com> a écrit :

# Steve Fink (6 years ago)

+1 from me for !in. It's a surprisingly common nuisance.

And I don't care for the !obj.x workaround at all -- even if you can survive the difference in semantics, from a code reading point of view this is saying something entirely different.

And it is very different semantically. 'x' in obj does [[HasProperty]]; obj.x does [[GetProperty]]. With

obj = { get x() { print("getter"); return 3; } };

then |"x" in obj| does not print "getter" while |obj.x| does.

# Naveen Chawla (6 years ago)

I don't use in.

What do I get with 'x' !in obj or !(x in obj) that I don't get with !obj['x'] ?

Genuinely asking - I don't know what I am missing.

I use obj[x] because I believe it's a more familiar syntax and I believe I get the same outcome..(?)..

# Jordan Harband (6 years ago)

!obj.x will return true for any falsy property - null, undefined, positive or negative zero, NaN, and the empty string. !(x in obj) will return true only if x is not an own property on obj nor anything in its prototype chain. They are decidedly different tests and they check for decidedly different things.

# Naveen Chawla (6 years ago)

Good point. I've never needed falsey valid values in my obj/maps yet, so it'll continue to be very rare that I will need to use in (and I'll continue to prefer !obj.x when I don't).

However, for this proposal I would prefer a new keyword like notin instead of !in, because the ! followed by a word normally indicates the inverse boolean of a value in other cases, whereas a clean break like notin I think seems clearer. Reserved keyword would probably be needed though?

# kai zhu (6 years ago)

-1

this feature mostly cross-cuts "!obj.hasOwnProperty('foo')". the only semantic-difference is "in" will check prototype-chain as jordan pointed out (and widely regarded as a bad design-pattern), while "hasOwnProperty" [correctly] will not. in every real-world use-case i've encountered, hasOwnProperty is what you actually want instead of in. and for looping, "Object.keys(obj).forEach(...)" is usually faster than "for (key in obj) {...}" (partly because of again, the bad-design prototype-chain lookup inherent with "in").

also, imagine the cognitive-load placed on yourself when debugging integration-javascript with a mix of these cross-cutting design-patterns:

// can you easily spot where the subtle integration-bug is
// when dealing with code has a mashup of
// in and hasOwnProperty?

if ('foo' !in obj) {
    ...
}
...
if (!obj.hasOwnProperty('bar') {
    ....
}

in summary for those who like to adhere to the python/jslint philosopy of "there should be one and preferably only one way to do any given task":

  1. for property-checks, "hasOwnProperty" is generally the one-and-only correct-way to do it.
  2. for looping over properties, "Object.keys(obj).forEach(...)" is generally the one-and-only correct-way to do it.

following the above 2 guidelines will save you alot of needless cognitive-load when doing integration-debugging of web-projects.

# Barret Furton (6 years ago)

Mixing the semantics of a unary operator with a binary operator seems... not ideal.

# Guylian Cox (6 years ago)

It isn't that different from mixing == with ! to get !=

Le mer. 11 juil. 2018 à 15:51, Barret Furton <barretfurton at gmail.com> a écrit :

# Barret Furton (6 years ago)

Good point.

# Andrea Giammarchi (6 years ago)

and, as previously mentioned, !obj.x might have side effects through the accessor, as example in every lazily defined property that would be early defined (or anything else behind a getter that could do more than just telling the property is there and it's not truthy).

I have mixed feelings about !in and I also wonder if something like const not = $ => !$; would make checks look nicer: if (not('x' in obj)) { ... }

but that's not really a syntax shortcut, isn't it? Probably a ni would be better, as new not in relational operator? I wouldn't like notIn or notin much, but I might use it anyway.

# Alex Vincent (6 years ago)

---------- Forwarded message ---------- From: Andrea Giammarchi <andrea.giammarchi at gmail.com> To: Jordan Harband <ljharb at gmail.com> Cc: "es-discuss at mozilla.org" <es-discuss at mozilla.org> Bcc: Date: Wed, 11 Jul 2018 16:23:03 +0200 Subject: Re: Small Proposal "!in" and, as previously mentioned, !obj.x might have side effects through the accessor, as example in every lazily defined property that would be early defined (or anything else behind a getter that could do more than just telling the property is there and it's not truthy).

Peanut gallery observation: I personally think !in is a Really Bad Idea, or at least I'm not convinced that it's particularly useful. If it is useful, then let one of the transpiling languages like CoffeeScript or TypeScript demonstrate it first.

Also, there's the little matter of pronunciation. I admit to a bit of snarkiness when I first saw this proposal, but I didn't expect it to have any traction. So I'll just say it: do we really want JavaScript to be a "bangin' " language?

Alex

# Ben Wiley (6 years ago)

I find the juxtaposition of a symbol operator against an English operator a bit odd, but I think most English speakers pronounce "!" as "not" so you might not have so much to worry about..

Le mer. 11 juill. 2018 11 h 24, Alex Vincent <ajvincent at gmail.com> a écrit :

# Alex Vincent (6 years ago)

In Linux programming, #!/bin/bash is very commonly the first line of a shell script. In Python, we have #!/bin/python, or #!/bin/perl. The #! characters are pronounced "she-bang", because # is pronounced "hash" and ! is pronounced "bang". en.wikipedia.org/wiki/Shebang_(Unix)

# Isiah Meadows (6 years ago)

Let me compound on that: Kotlin has a !in for "not in collection" and !is for "not an instance of". I've been using that language quite a bit lately out of necessity (better than Java, and all the other alternatives suck in some way), and those two operators just feel wrong to type. It's to the point I'm sometimes coding my way out of writing them. (No other feature uses this symbol except for literal logical negation.)

Oh, and as I mentioned before, key in object checks the prototype chain, which in my experience is not the thing you usually want to do.

So I agree this is a Really Bad Idea™, for this above if not the Kotlin reference.

# T.J. Crowder (6 years ago)

On Wed, Jul 11, 2018 at 4:51 PM, Alex Vincent <ajvincent at gmail.com> wrote:

In Linux programming, #!/bin/bash is very commonly the first line of a

shell

script. In Python, we have #!/bin/python, or #!/bin/perl. The #!

characters

are pronounced "she-bang", because # is pronounced "hash" and ! is pronounced "bang".

Indeed. But in JavaScript (and Java and C and C# and...), ! is "not", and I for one read it that way when reading anything other than bash script. I don't read !== as "bang equal," either. (Which in British English would be really misleading...)

And that's why I like the idea of !in (or notin), because I'd much rather read and write "if property not in object" than "if not property in object" (and don't get me started on the parens required to make it work :-) ).

To me, !in or notin or whatever you want makes perfect sense, just like we have != and !==. It's like not having !== and then arguing we don't need to have it because after all, you can write n != 1 as !(n == 1).

Heck, all we really need is NAND gates, right? ;-)

On Wed, Jul 11, 2018 at 6:33 PM, Isiah Meadows <isiahmeadows at gmail.com>

wrote:

So I agree this is a Really Bad Idea™, for this above if not the Kotlin reference.

I strongly disagree it's a Really Bad Idea™. I think it's a Moderately Good Idea On The Whole™. And !in is fine by me but I'm also happy with notin or whatever.

I just don't expect it to happen. Too much inertia to add it after-the-fact, and too many bigger fish to fry. :-)

-- T.J. Crowder

# Mike Samuel (6 years ago)

On Wed, Jul 11, 2018 at 1:51 PM T.J. Crowder < tj.crowder at farsightsoftware.com> wrote:

On Wed, Jul 11, 2018 at 4:51 PM, Alex Vincent <ajvincent at gmail.com> wrote:

In Linux programming, #!/bin/bash is very commonly the first line of a shell script. In Python, we have #!/bin/python, or #!/bin/perl. The #! characters are pronounced "she-bang", because # is pronounced "hash" and ! is pronounced "bang".

Indeed. But in JavaScript (and Java and C and C# and...), ! is "not", and I for one read it that way when reading anything other than bash script. I don't read !== as "bang equal," either. (Which in British English would be really misleading...)

And that's why I like the idea of !in (or notin), because I'd much rather read and write "if property not in object" than "if not property in object" (and don't get me started on the parens required to make it work :-) ).

To me, !in or notin or whatever you want makes perfect sense, just like we have != and !==. It's like not having !== and then arguing we don't need to have it because after all, you can write n != 1 as !(n == 1).

Heck, all we really need is NAND gates, right? ;-)

On Wed, Jul 11, 2018 at 6:33 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

So I agree this is a Really Bad Idea™, for this above if not the Kotlin reference.

I strongly disagree it's a Really Bad Idea™. I think it's a Moderately Good Idea On The Whole™. And !in is fine by me but I'm also happy with notin or whatever.

I agree with all your arguments about why it's more ergonomic, but I keep coming back to what Naveen said: "I don't use in."

I think in is the wrong operator to make more convenient, except as part of a more general cleanup to provide inverted forms of boolean infix operators.

Usually, where I see in I would prefer that the author had used hasOwnProperty. And usually where I see (foo.hasOwnProperty(p)), I would prefer the author wrote Reflect.apply(hasOwnProperty, foo, [p]).

What are the use cases for in that would not be better served by an ergonomic, infix hasOwnProperty?

I just don't expect it to happen. Too much inertia to add it

# alexander at debenclipper.com (6 years ago)

This may be a silly idea that doesn't come naturally to others, but the first thing I thought of was "!n", where the "!" represents a flipped "i", so the inverse of in.

Although, on the discussion of "notin" or "!in", the latter comes far more naturally to me as others have mentioned.

# Michael Theriot (6 years ago)

I think in and instanceof could both benefit from having negated versions.

Assuming the developer is using in correctly, hasOwnProperty concerns are irrelevant. Either way they would attempt to use !(a in b), not !hasOwnProperty.

Same reason we don't use... !(a == b) // a != b !(a === b) // a !== b !(a > b) // a <= b (!(a > b) && !(a == b)) // a < b

# Mike Samuel (6 years ago)

On Wed, Jul 18, 2018 at 11:05 AM Michael Theriot < michael.lee.theriot at gmail.com> wrote:

I think in and instanceof could both benefit from having negated versions.

Assuming the developer is using in correctly, hasOwnProperty concerns are irrelevant. Either way they would attempt to use !(a in b), not !hasOwnProperty.

Why should we assume the developer is using in correctly? Apologies if I buried my question at the end. It was, what are the use cases for in that would not be better served by an ergonomic, infix hasOwnProperty?

Same reason we don't use...

!(a == b) // a != b !(a === b) // a !== b

!(a > b) // a <= b (!(a > b) && !(a == b)) // a < b

I'm not sure this is relevant to your larger point, and I've already conceded ergonomics, but these last two are not equivalent because NaN is weird.

a = NaN, b = 0 [!(a > b), a <= b] // [true, false] [!(a > b) && !(a == b), a < b] // [true, false]

# Mike Samuel (6 years ago)

[sorry dropped group]

On Fri, Jul 13, 2018 at 11:36 AM <alexander at debenclipper.com> wrote:

This may be a silly idea that doesn't come naturally to others, but the first thing I thought of was "!n", where the "!" represents a flipped "i", so the inverse of in.

You'd need yet another restricted production which would make infix in unrestricted but the negation restricted.

x // no semicolon inserted in (obj)

x // semicolon inserted !n (obj)

Not a blocker, but worth keeping in mind. I also have to look hard at them to distinguish.

# Michael Theriot (6 years ago)

I think it is irrelevant; the operator already exists and I would assume if you want the negation of it you are using it correctly in the first place. Otherwise are you not just arguing for its removal altogether? But to answer your question one case that comes to mind is trapping get/has in a proxy handler.

# Mike Samuel (6 years ago)

On Wed, Jul 18, 2018 at 12:21 PM Michael Theriot < michael.lee.theriot at gmail.com> wrote:

I think it is irrelevant; the operator already exists and I would assume if you want the negation of it you are using it correctly in the first place. Otherwise are you not just arguing for its removal altogether? But to answer your question one case that comes to mind is trapping get/has in a proxy handler.

Why should we assume that only people who consistently use in correctly would want the negation? It seems that people who use it incorrectly because they are confused about the precise semantics or don't care might want the negation too. If there are more of the latter then we should not assume what you assume.

Proxy handler code is important, but very few developers will ever write a proxy handler over their careers, so this seems like a marginal use case. Besides, Reflect.has is probably a better choice in a proxy handler.

I am not arguing for removing in. That would break the web. I am just arguing for prioritizing changes that provide features that more closely match the semantics developers typically want over making it more convenient to write code that seems to work in casual testing but has subtly wrong semantics.

# Tobias Buschor (6 years ago)

There are valid use-cases. As an example, some browsers have "onfocus" as an own property of "window", some as an inherited.

if ('onfocus' !in window) {
    // polyfill onfocus...
}

Am Mi., 18. Juli 2018 um 18:32 Uhr schrieb Mike Samuel <mikesamuel at gmail.com

# Andy Earnshaw (6 years ago)

Although I support the idea of !in (for the same reasons as T.J. Crowder mentioned, plus it's useful for duck typing), what some browsers do isn't a great argument as modern browsers follow the spec more closely with to inherited accessors like this and you'd never be able to use !in for an older browser. However, you do have a point in that accessors can live anywhere in the prototype chain and an object's properties may not necessarily be 'owned' by the object in question:

document.createElement('input').hasOwnProperty('type')
// false

So far, the main argument against has been that hasOwnProperty() is recommended over in as a more robust check. I don't see how this is a valid concern, they clearly have different use cases and you're not going to solve that problem be excluding a negated in from the spec (!(a in b) is still easier to type than !b.hasOwnProperty(a)). There are plenty of valid use cases for in, not least duck typing as mentioned before:

function feed(duck) {
    if ('quackPitch' in duck && duck.canSwim) {
        duck.give(defrostedPeas);
    }
}

!in and !instanceof would be great additions to the operator sets.

# Mike Samuel (6 years ago)

On Thu, Jul 19, 2018 at 7:32 AM Andy Earnshaw <andyearnshaw at gmail.com>

wrote:

Although I support the idea of !in (for the same reasons as T.J. Crowder mentioned, plus it's useful for duck typing), what some browsers do isn't a great argument as modern browsers follow the spec more closely with to inherited accessors like this and you'd never be able to use !in for an older browser. However, you do have a point in that accessors can live anywhere in the prototype chain and an object's properties may not necessarily be 'owned' by the object in question:

document.createElement('input').hasOwnProperty('type')
// false

'string' === typeof document.createElement('input').type // true

So far, the main argument against has been that hasOwnProperty() is recommended over in as a more robust check. I don't see how this is a valid concern, they clearly have different use cases and you're not going to solve that problem be excluding a negated in from the spec (!(a in b) is still easier to type than !b.hasOwnProperty(a)). There are plenty of valid use cases for in, not least duck typing as mentioned before:

Agree re "not solving that problem by" When I'm duck typing, I typically am testing typeof or truthiness of a property, not just presence.

function feed(duck) {
    if ('quackPitch' in duck && duck.canSwim) {
        duck.give(defrostedPeas);
    }
}

This code is brittle. An attacker may be able to deny service by getting { "quackPitch": true, "canSwim": true } to a JSON decoder, but would not be able to trigger an exception if you tested with typeof instead of in.

function robustFeed(duck) { if (duck.canSwim && typeof duck.give === 'function') { duck.give(defrostedPeas); } }

in provides a weak, confusable kind of duck typing. JSON decoding attacks allow forging objects that satisfy in predicates, encouraging conflating objects from an untrusted source with objects from trusted code. These forgeries often would not pass stronger predicates that test for the typeof required properties.

!in and !instanceof would be great additions to the operator sets.

Agree re !instanceof. I'm still not seeing where developers do and should use in or !in on a regular basis.

# Michael Theriot (6 years ago)

'string' === typeof document.createElement('input').type // true

It should be noted this is a "loose check"; it does not determine whether or not the property exists when its value equals undefined. It also triggers getters, whereas in reports whether or not the property exists without triggering a getter.

# T.J. Crowder (6 years ago)

On Thu, Jul 19, 2018 at 12:32 PM, Andy Earnshaw <andyearnshaw at gmail.com> wrote:

Although I support the idea of !in (for the same reasons as T.J. Crowder mentioned, plus it's useful for duck typing), what some browsers do isn't

a

great argument as modern browsers follow the spec more closely with

to inherited accessors like this and you'd never be able to use !in for

an

older browser.

Well, there's transpiling.

!in and !instanceof would be great additions to the operator sets.

AND, agreeing with Mike Samuel, an ergonomic operator for hasOwnProperty (that doesn't have the issues of being overridden, not being inherited because Object.prototype isn't in the object's prototype chain, etc.) would be a great addition. I don't see any reason they couldn't all be part of the same proposal as they touch the same parts of the spec and implementations. And agree that the own property ones would be the more useful ones, but there are use cases for both.

The immediate temptation is hasOwn and !hasOwn. My only concern is that their operands would be in the opposite order to in and !in:

const o = Object.create({a: 1});
o.b = 2;
console.log("a" in o);     // true
console.log(o hasOwn "a"); // false
console.log("b" in o);     // true
console.log(o hasOwn "b"); // true

For me, hasOwn with the different operand order isn't a problem, but others may take a different view. Trying to keep the same order takes us down a route like inOwn which I can't say I care for.

But I wonder if all of this discussion is useful. If someone did take the time to work out the naming and do a proper draft proposal, perhaps a Babel plugin, is there really any likelihood of someone championing it? I'd see these contents:

  • name !in obj, name notin obj, or whatever it gets called
  • obj hasOwn name, name inOwn obj, or whatever it gets called
  • obj !hasOwn name, name !inOwn obj, or whatever it gets called
  • Reflect.hasOwn, the "own" version of Reflect.has
  • Proxy trap for hasOwn (even if the operator has a different name)

Is there anyone appropriately-placed who can say "Yeah, if someone spends the time to investigate this and put together a really proper proposal, I'm willing to look at that proposal with an eye toward possibly championing it." I mean, if there's a 10% chance or better, it may be worth someone's time. If there isn't, then...

-- T.J. Crowder

# Mike Samuel (6 years ago)

On Thu, Jul 19, 2018 at 9:26 AM Michael Theriot < michael.lee.theriot at gmail.com> wrote:

'string' === typeof document.createElement('input').type // true

It should be noted this is a "loose check"; it does not determine whether or not the property exists when its value equals undefined. It also triggers getters, whereas in reports whether or not the property exists without triggering a getter.

Good point. in does trigger "has" proxy handlers though, so neither is side-effect free.

# T.J. Crowder (6 years ago)

On Thu, Jul 19, 2018 at 2:44 PM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote:

Is there anyone appropriately-placed who can say "Yeah, if someone spends the time to investigate this and put together a really proper proposal,

I'm

willing to look at that proposal with an eye toward possibly championing it."

Apologies, Mike, I just realized you're a potential champion. Just in case you read that as seeming a bit off... :-)

-- T.J. Crowder

# Andy Earnshaw (6 years ago)

It was a contrived example I threw together to make a point in 30 seconds. It may surprise you to know that it is not real world code. You talk about an "attacker" as if any code working in such a way is sensitive, but that is often not the case and leaving your functions intentionally generic allows third parties more room when working with it.

'string' === typeof document.createElement('input').type // true

Again, you're missing the point, which is how that is one example of an object that doesn't 'own' all of its properties. As already mentioned, it also triggers a getter.

Let's not also forget that not all code has to adhere to best practices. I use the in operator far more in the REPL/console or when I'm prototyping than I do when I'm performing robust checks in code.

# Naveen Chawla (6 years ago)

I still prefer truthy checks when logically valid. Otherwise a truthy check + [any other validity check in the logic]. I find in far too quirky and I'd rather never ever use it.

I think instanceof is also a messy pattern. I've always preferred having an overridden method on the object that performs the necessary logic for that type, instead of if(x instanceof Y)... I find overridden method based code shorter at the point of use, and scales to many instances / permutations for type based logic.

Therefore, I'd rather TC39 let these concepts like in and instanceof die quietly, and always focus on the more/most powerful ways of getting things done first.

# Andy Earnshaw (6 years ago)

On Thu, 19 Jul 2018 at 14:44 T.J. Crowder <tj.crowder at farsightsoftware.com>

wrote:

On Thu, Jul 19, 2018 at 12:32 PM, Andy Earnshaw <andyearnshaw at gmail.com> wrote:

Although I support the idea of !in (for the same reasons as T.J. Crowder mentioned, plus it's useful for duck typing), what some browsers do isn't a great argument as modern browsers follow the spec more closely with

to inherited accessors like this and you'd never be able to use !in for an older browser.

Well, there's transpiling.

Good point.

!in and !instanceof would be great additions to the operator sets.

AND, agreeing with Mike Samuel, an ergonomic operator for hasOwnProperty (that doesn't have the issues of being overridden, not being inherited because Object.prototype isn't in the object's prototype chain, etc.) would be a great addition. I don't see any reason they couldn't all be part of the same proposal as they touch the same parts of the spec and implementations. And agree that the own property ones would be the more useful ones, but there are use cases for both.

The immediate temptation is hasOwn and !hasOwn. My only concern is that their operands would be in the opposite order to in and !in:

I'm not against this at all. I just think the arguments against !in aren't really arguments against it. Adding !hasOwn would give even more weight to an !in proposal, I think.

For me, hasOwn with the different operand order isn't a problem, but others may take a different view. Trying to keep the same order takes us down a route like inOwn which I can't say I care for.

Nor me. I would argue for on ('a' on b), but that is a huge typo footgun (especially for Colemak users) and maybe isn't clear enough about its semantics. I would argue that operators aren't camel cased in JS though, so hasown/inown.

But I wonder if all of this discussion is useful. If someone did take the time to work out the naming and do a proper draft proposal, perhaps a Babel plugin, is there really any likelihood of someone championing it? I'd see these contents:

  • name !in obj, name notin obj, or whatever it gets called
  • obj hasOwn name, name inOwn obj, or whatever it gets called
  • obj !hasOwn name, name !inOwn obj, or whatever it gets called
  • Reflect.hasOwn, the "own" version of Reflect.has
  • Proxy trap for hasOwn (even if the operator has a different name)

Is there anyone appropriately-placed who can say "Yeah, if someone spends the time to investigate this and put together a really proper proposal, I'm willing to look at that proposal with an eye toward possibly championing it." I mean, if there's a 10% chance or better, it may be worth someone's time. If there isn't, then...

!in and !instanceof are low hanging fruit (run the same steps as their counterparts but flip the result), better off in their own proposal. I don't know if you'd find a champion to do it, but I do think a lot of people would find them convenient.

# Andy Earnshaw (6 years ago)

On Thu, 19 Jul 2018 at 14:48 Mike Samuel <mikesamuel at gmail.com> wrote:

On Thu, Jul 19, 2018 at 9:26 AM Michael Theriot < michael.lee.theriot at gmail.com> wrote:

'string' === typeof document.createElement('input').type // true

It should be noted this is a "loose check"; it does not determine whether or not the property exists when its value equals undefined. It also triggers getters, whereas in reports whether or not the property exists without triggering a getter.

Good point. in does trigger "has" proxy handlers though, so neither is side-effect free.

Except I'd argue this is a desirable side effect in the case of in and less so in the case of a getter. Getters are more likely to be an intensive operation (for example, innerHTML) than a proxy has operation generally overriding the expected behaviour of the target object.

# Augusto Moura (6 years ago)

In most of the use cases of checking if a property is in the prototype chain (checking a protocol for example) you do want to trigger getters and Proxy traps. When interfacing with a object a developer doesn't need to be concerned with the implementation behind, if a getter or proxy trap does a intensive computation or has side effects, it's all bad class/object design fault. A common example when you want to check a property "return" rather than it's existence it's virtual properties or class refactoring:

// old implementation
class Foo {
  constructor() {
    this.foo = 46;
  }
}

// post refactoring
class Foo {
  // implements something different

  // Product of refactoring, undefined it's a placeholder here
  //it can be any value that makes sense in the refactoring
  get foo() { return undefined; }
  set foo(_) {}
}

Of course there's some use cases to use property check without triggering side effects (mostly when working with property descriptors), but the majority of "property existence check" lays on interface assertion and a typeof check it's ~generally~ the right choice.

About the !in operator, I don't see any problem in it. Of couse the usage of in is most of the time is not recommended, but it has it place. Also it puts precedence to future operators (like the hasOwn proposed here).

# Mike Samuel (6 years ago)

On Thu, Jul 19, 2018 at 10:40 AM Augusto Moura <augusto.borgesm at gmail.com>

wrote:

Of couse the usage of in is most of the time is not recommended, but it has it place.

What places does it have? I remain unconvinced that in has significant enough use cases to warrant high-level ergonomics were it being proposed today.

It exists, and it'll probably never be removed from the language, but I don't think it should be taught as a good part of the language, and linters should probably flag it.

# Michael Theriot (6 years ago)

For me, hasOwn with the different operand order isn't a problem, but

others may take a different view. Trying to keep the same order takes us down a route like inOwn which I can't say I care for.

Nor me. I would argue for on ('a' on b), but that is a huge typo footgun (especially for Colemak users) and maybe isn't clear enough about its semantics. I would argue that operators aren't camel cased in JS though, so hasown/inown.

For what it's worth I was also thinking of an "on" operator when reading this message, so this is intuitive to me. I also think that is a separate idea to propose though.

Of couse the usage of in is most of the time is not recommended, but it

has it place.

What places does it have? I remain unconvinced that in has significant enough use cases to warrant high-level ergonomics were it being proposed today.

It exists, and it'll probably never be removed from the language, but I don't think it should be taught as a good part of the language, and linters should probably flag it.

Maybe a radical thought, but does this not apply to hasOwnProperty? If you have strong type management why test for a property? The one case I can think of is parsing JSON but I handle that with destructuring. Are there significant use cases for it? Should linters flag it?

# Mike Samuel (6 years ago)

On Thu, Jul 19, 2018 at 11:56 AM Michael Theriot < michael.lee.theriot at gmail.com> wrote:

For me, hasOwn with the different operand order isn't a problem, but

others may take a different view. Trying to keep the same order takes us down a route like inOwn which I can't say I care for.

Nor me. I would argue for on ('a' on b), but that is a huge typo footgun (especially for Colemak users) and maybe isn't clear enough about its semantics. I would argue that operators aren't camel cased in JS though, so hasown/inown.

For what it's worth I was also thinking of an "on" operator when reading this message, so this is intuitive to me. I also think that is a separate idea to propose though.

"on" is a good name. Agree on separate.

Of couse the usage of in is most of the time is not recommended, but it

has it place.

What places does it have? I remain unconvinced that in has significant enough use cases to warrant high-level ergonomics were it being proposed today.

It exists, and it'll probably never be removed from the language, but I don't think it should be taught as a good part of the language, and linters should probably flag it.

Maybe a radical thought, but does this not apply to hasOwnProperty? If you have strong type management why test for a property? The one case I can think of is parsing JSON but I handle that with destructuring. Are there significant use cases for it? Should linters flag it?

Good questions. Linters should flag x.hasOwnProperty(y) since if you're unsure whether x has an own property y you're probably unsure whether x has an own property 'hasOwnProperty'.

IIRC, destructuring traverses prototypes so see caveat about library code and monkeypatching below. const { toString: f } = {} typeof f // 'funciton'

You're right that in the middle of an application an instance's type should determine whether a property is present. There are use cases at the periphery.

Use cases in bleeding edge JS include

  • As you noted, operations on parsed JSON. Even if you use revivers to parse JSON to Maps instead of Objects you either need own property checks or Object.setPrototypeOf(parsed, null) when populating the Map.
  • Non-clobbering mass assignment. Like Object.assign but that doesn't overwrite existing properties in the assignee.
  • Reliable hole detection in arrays: (1 !on [0, , 2])
  • Adapters that use naming conventions between JS objects and external systems, like between database field names and JS property names.
  • Distinguishing between user-code-defined properties on a host object like an HTML element and readonly host properties.

Many use cases for hasOwnProperty could be better supported by Map, Set, and Object.create(null) including:

  • Objects used as lookup tables.
  • Lookup tables with special purpose fallback logic like message bundles that fall back from locale 'aa-BB' to 'aa'.
  • Configuration objects.
  • Function options bundles. but idiomatic JS hasn't caught up and some library code has to run on old interpreters, so a transpiling on would be nice. The last two are mostly an issue in library code that needs to be resilient when loaded alongside monkeypatched prototypes.

Honorable mention:

  • for(...in...) iteration broken solved by for(...of...):
# Isiah Meadows (6 years ago)

"on" is a good name. Agree on separate.

Throwing another operator name out there: what about obj has "foo" instead?

Either way, it's a new context-sensitive keyword in a very awkward position.

  • Non-clobbering mass assignment. Like Object.assign but that doesn't overwrite existing properties in the assignee.

Could this be a new built-in function instead? Maybe, Object.defaults?

Of course, this is a pretty hard tangent from the original thread.

Many use cases for hasOwnProperty could be better supported by Map, Set, and Object.create(null) including: ...

  • Configuration objects.
  • Function options bundles.

Not sure these would work well as maps, since it's far easier to just use dictionary objects as named arguments. Clojure and Ruby are the two main languages I know that use hash maps exclusively for named parameters with any frequency, and that's because map/hash lookup is as easy as property lookup.

  • Java and C++ use builders. (Java separates the two, while C++ merges them.)
  • C and Rust use structs.
  • JavaScript and Lua use simple untyped objects.
  • Kotlin, Scala, Swift, C#, Python, and Objective C use native named arguments that are resolved internally.
  • Even Ruby added sugar to support its common idiomatic use of hashes as named arguments.

Isiah Meadows me at isiahmeadows.com, www.isiahmeadows.com

# Jacob Pratt (6 years ago)

Throwing another operator name out there: what about obj has "foo"

instead?

As someone who has just been casually following this issue, I'd much prefer has over on. I was going to stay quiet, but only because I didn't have a better alternative.

jhpratt

# Augusto Moura (6 years ago)

The only use that came to mind was detecting a property descriptor in a prototype chain. Sure is not a day to day use case, but it's useful when writing libraries that involve descriptor modifications (decorators, for example, will largely involve it). Recently I had to get the descriptor of properties in a potencial deep inheritance (current Object helpers only return own descriptors), and used the in operator to guard the prototype recursive search.

const searchRecursivelyPropDescriptor = (obj, prop) =>
  !obj
    ? undefined
    : Object.getOwnPropertyDescriptor(obj, prop) ||
searchRecursivelyPropDescriptor(Object.getPrototypeOf(obj), prop);

const getPropertyDescriptor = (obj, prop) =>
  prop in obj ? searchRecursivelyPropDescriptor(obj, prop) : undefined;

Anyways, we can't simply ignore the operator, if we are getting a !instance and opening precedence to future operators (!on or !hasOwn) I don't see any problems with a !in. Legacy bad design should not affect language consistency of new features.

# Steve Fink (6 years ago)

This reads a little oddly, but another syntax option would be prop in.own obj (equivalent to obj.hasOwnProperty(prop)) and then prop !in.own obj.

Or perhaps in.own should be Object.prototype.hasOwnProperty.call(obj, prop)?

Though this makes me think it would be nice to have something like name in.map mymap (equivalent to mymap.has(name))

# T.J. Crowder (6 years ago)

On Tue, Jul 24, 2018 at 12:28 AM, Steve Fink <sphink at gmail.com> wrote:

Or perhaps in.own should be Object.prototype.hasOwnProperty.call(obj, prop)?

It should just use the abstract HasOwnProperty operation directly.

-- T.J. Crowder