Fixing the associativity / precedence of the instanceof operator

# Charles Pick (11 years ago)

Hello, forgive me if this has come up before, I couldn't find any discussions via Google.

One regular, annoying mistake I see people making is combining the ! operator with instanceof:

if (!foo instanceof Foo) { ... }

of course, this must be written with extra parentheses:

if (!(foo instanceof Foo)) { ... }

My question is, why? There are no circumstances where the developer intended to write the first version, it's a typo and will always evaluate to false, even when using Boolean. Therefore would it be possible to fix the precedence so that the first version is parsed the same way as the second?

,

Charles

# Till Schneidereit (11 years ago)

On Mon, Aug 25, 2014 at 12:40 PM, Charles Pick <charles at codemix.com> wrote:

Hello, forgive me if this has come up before, I couldn't find any discussions via Google.

One regular, annoying mistake I see people making is combining the ! operator with instanceof:

if (!foo instanceof Foo) { ... }

of course, this must be written with extra parentheses:

if (!(foo instanceof Foo)) { ... }

My question is, why? There are no circumstances where the developer intended to write the first version, it's a typo and will always evaluate to false, even when using Boolean. Therefore would it be possible to fix the precedence so that the first version is parsed the same way as the second?

While I agree that the associativity should be different, changing this won't work: there are probably tens of thousands of websites and node.js scripts and what have you out there that would break, because the rely on the current behavior. (Many of them probably because someone "fixed" the associativity issue by inverting the contents of then and else blocks instead of the condition.) Yes, those sites use somewhat broken code, but users don't care as long as they work.

# Charles Pick (11 years ago)

I agree that this could cause some problems, however, that code has never been correct in the first place. It's the equivalent of writing if (false) {...}. Seems like it's reasonable to fix something if it only has an impact on code which is already broken.

# Salvador de la Puente González (11 years ago)

Before doing that, I would propose to introduce not, and and or with fixed associativity or even a notinstanceof for that case before changing the semantics of ! operator. Indeed I think !object instance of class is less readable than !(object instanceof class).

# Till Schneidereit (11 years ago)

On Mon, Aug 25, 2014 at 1:01 PM, Charles Pick <charles at codemix.com> wrote:

I agree that this could cause some problems, however, that code has never been correct in the first place. It's the equivalent of writing if (false) {...}. Seems like it's reasonable to fix something if it only has an impact on code which is already broken.

The logic might be broken, yes, but the application's observable behavior might not. At least not so much as to make the application unusable. E.g., an application might turn from always showing some info where the developer intended it to not be shown under exceptional circumstances to never showing it. A form might go from always marking a field as valid to never doing so, making it impossible to commit and the application unusable in its entirety.

# Charles Pick (11 years ago)

Ok, what if !foo instanceof Foo became a strict mode error instead?

# Barronville, Jonathan (11 years ago)

I’m on the same page as Charles. I feel like it should be okay to fix something like this … at least in strict mode. Or introduce a tiny bit of new grammar supporting something like foo ! instanceof Foo (or foo not instanceof Foo) maybe?

  • Jonathan

Sent from Mailbox

# Till Schneidereit (11 years ago)

On Tue, Aug 26, 2014 at 5:48 AM, Charles Pick <charles at codemix.com> wrote:

Ok, what if !foo instanceof Foo became a strict mode error instead?

That'd increase the difference between the two modes, which is something nobody wants. Also, someone employing strict mode is also quite a bit more likely to use developer tools such as linters. Those certainly should warn about code like that.

On Tue, Aug 26, 2014 at 11:54 AM, Barronville, Jonathan < jonathan at belairlabs.com> wrote:

I’m on the same page as Charles. I feel like it should be okay to fix something like this … at least in strict mode.

Browser vendors would have to make the change, and users just switch browsers if sites break. Users don't care about a change being for the better on a conceptual level. Really, the only backwards-incompatible changes we can introduce are in areas where either features were almost entirely unused (very rare with a tail as long as the web's!) or engines disagree so much as to make specific patterns impossible to use.

Or introduce a tiny bit of new grammar supporting something like foo ! instanceof Foo (or foo not instanceof Foo) maybe?

How would that help? You can already write perfectly correct code for this with !(foo instanceof Foo). Your proposal would add one more way of expressing what you want, but it won't make the wrong way any more right.

# Alex Kocharin (11 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20140826/cc0e6fc8/attachment

# Alex Kocharin (11 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20140826/bb2e28d1/attachment

# Till Schneidereit (11 years ago)

On Tue, Aug 26, 2014 at 3:38 PM, Alex Kocharin <alex at kocharin.ru> wrote:

use developer tools such as linters. Those certainly should warn about code like that.

I was trying to find such a tool a few days ago (after similar error was fixed in bunyan), and I found nothing:

gist.github.com/rlidwka/8b904ca00b1e76731270

So I agree that it should be catched by linters, but there are no good linters as of now. :(

That's bad. Did you file bugs against at least the more popular tools?

# Nathan Wall (11 years ago)

An isnt operator has been proposed before[1].

Parens are ugly. Proto[2] supports negating operators with ! (foo !in bar, foo !is bar, foo !like bar).

[1] harmony:egal [2] Nathan-Wall/proto

# Alex Kocharin (11 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20140826/64f7a5ef/attachment-0001

# Andrea Giammarchi (11 years ago)

I sort of like the ! not operation as !instanceof in order to both obj instanceof(Object) and obj !instanceof(Object) but I find other ideas not so bad too, here a couple of examples:

// via Objects
Object.defineProperty(
  Object.prototype,
  'instanceOf',
  {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function (Constructor) {
      return this instanceof Constructor;
    }
  }
);

console.log({}.instanceOf(Object));  // true
console.log(!{}.instanceOf(Object)); // false

// via constructors
Object.defineProperty(
  Function.prototype,
  'isInheritedBy',
  {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function (obj) {
      return obj instanceof this;
    }
  }
);

console.log(Object.isInheritedBy({}));   // true
console.log(!Object.isInheritedBy({}));  // false

console.log(Object.isInheritedBy(
  Object.create(null)
));   // false