JavaScript's Forgotten Keyword (with)
Randall

Randall @mistval

About: I'm a coder who has worn a lot of hats, from individual contributor to lead engineer to "CTO" (yes, in quotes, make of that what you will!). I've plenty to learn and hopefully some to share as well.

Joined:
Jun 20, 2020

JavaScript's Forgotten Keyword (with)

Publish Date: Jul 29 '21
198 14

Being a JavaScript developer can be an exciting job. Almost every day you will find something mysterious and otherworldly. Sometimes that's a magical experience, other times it's downright frightening.

In this article we will take a look at the "with" keyword. It's one of those dark corners of the language that even veteran developers often are not aware of.

Usage

Let's use the with keyword to help us log a message to the console:

with (console) {
  log('I dont need the "console." part anymore!');
}
Enter fullscreen mode Exit fullscreen mode

And let's use it to help us join an array into a string:

with (console) {
  with (['a', 'b', 'c']) {
    log(join('')); // writes "abc" to the console.
  }
}
Enter fullscreen mode Exit fullscreen mode

Yes my friends, believe it or not, this is JavaScript.

What "with" Does

Here is the explanation from MDN:

JavaScript looks up an unqualified name by searching a scope chain associated with the execution context of the script or function containing that unqualified name. The 'with' statement adds the given object to the head of this scope chain during the evaluation of its statement body. If an unqualified name used in the body matches a property in the scope chain, then the name is bound to the property and the object containing the property. Otherwise a ReferenceError is thrown.

To reword that hopefully a little more simply: when you write an identifier in your code (like log or join in the above code snippet) there is a chain of objects that JavaScript looks at, and if one of those objects has a property with the same name as the identifier you wrote in your code, JavaScript uses the value of that property.

The with keyword lets you inject any arbitrary object into the front of that chain. Here's another example that might make that clearer:

with ({ myProperty: 'Hello world!' }) {
  console.log(myProperty); // Logs "Hello world!"
}
Enter fullscreen mode Exit fullscreen mode

Don't Use It

Awesome, right? Yeah, well, maybe not.

In most cases, the same effect can be achieved just by using temporary variables, which is easier than ever since the advent of destructuring.

In addition, MDN lists a number of pitfalls:

It's Forbidden in Strict Mode

You can't use with in strict mode. Considering that ES modules and classes are automatically in strict mode, this limitation kills even the possibility of using with in many modern use cases.

Accidental Shadowing

Consider the following code to average two numbers and round the result to an integer:

function getAverage(min, max) {
  with (Math) {
    return round((min + max) / 2);
  }
}

getAverage(1, 5);
Enter fullscreen mode Exit fullscreen mode

This returns NaN. Why? Because Math.min() and Math.max() shadow the function's arguments, so we end up calculating the sum of two functions, which of course, is NaN.

Basically if you use with, you suddenly have to be more careful about choosing identifiers. You have to go and look at what you are passing into with to make sure it does not have properties that might inadvertently shadow something else in a higher scope.

This behavior can also introduce security vulnerabilities. If an attacker is able to add properties to the object you pass to with, then they can shadow your identifiers and modify the behavior of your code in unexpected ways.

As one example, passing an object that was parsed from an unvalidated JSON HTTP request body to with would be extremely dangerous.

Performance

By adding something to the scope chain, you slow down just about every line of code, because you are increasing the number of objects that need to be searched to resolve your identifiers to values.

Ostracism

If you use the with keyword, everyone will think you are crazy and avoid you in the lunch room. Or maybe they will just look at you funny.

Either way, using magical language features that no one else knows about will make your code harder to maintain, and in this case won't gain you much.

Conclusion

The with keyword adds some interesting capabilities to the language, but ultimately it comes with too many downsides, and too few advantages, for me to be able to recommend using it.

Of course, don't just take it from me. MDN seems to hate it with a passion, and it is forbidden in strict mode for a reason.

I have been writing JavaScript for well over five years, and it amazes me that to this day I'm still learning language keywords that are not even remotely new. What else might be lurking out there?

Whence came with? Who envisioned it? Why? Did they want something like C++ namespaces? Did a Ouija board tell them to do it?

Whatever the case may be, it looks like the long-forgotten with statement will forever be relegated to the dustbin of history.

Though like many dark arts, it is fun to mess with!

Comments 14 total

  • Conrad Sollitt
    Conrad SollittJul 30, 2021

    An example of the one use case I can think of is for simple templating. For example Underscore uses it on the template() function which can be called from modern JS:

    underscorejs.org/docs/underscore-e...

    Personally I've used it only 1 time I remember after doing JS for 20+ years and it was to create a templating feature for Web Components.

  • meomeo
    meomeoJul 30, 2021

    This bring back so much memory when i was young and messing around with vb.net.

    • Mike Talbot ⭐
      Mike Talbot ⭐Jul 31, 2021

      If only JS with worked like the vb.net it would be much more useful and no accidental shadowing :)

  • Bryan Padron
    Bryan PadronJul 30, 2021

    The only time that I've used this is when in the node console where you can run
    with(process) { exit() }, but .exit is definitely a better way to exit

    • yw662
      yw662Jul 30, 2021

      Or let's make it process?.exit(), then you can use it anywhere :-)

  • Zevan Rosser
    Zevan RosserJul 30, 2021

    I always liked with :D... how about labels? I remember being weirded out the first time I saw them: developer.mozilla.org/en-US/docs/W...

  • George Mauer
    George MauerJul 31, 2021

    I've used it on a project where we created an in browser ide for days analysis. You would configure an object with properties for pluggable builtins, then surround the user's code in a with statement and emit it into a sandbox iframe.

  • Ovienadu Ken
    Ovienadu KenJul 31, 2021

    I saw this in a c# codebase a few days ago.

    Funny how it's usage is similar

  • tadeassoucek
    tadeassoucekJul 31, 2021

    Pascal has a with ... do ... statement, which behaves in the same way as in JS.

  • Akash
    AkashJul 31, 2021

    You have a good sense of humour :D. Nicely written article.

  • Samuel-Zacharie FAURE
    Samuel-Zacharie FAUREAug 3, 2021

    "If you use the with keyword, everyone will think you are crazy and avoid you in the lunch room. Or maybe they will just look at you funny."

    As they should.

  • Froxx93
    Froxx93Aug 4, 2021

    Wow, this sounds absolutely horrible from today's point of view 😅 I wonder what the original idea behind it was. I mean what made the devs think something like this would be necessary or improve the language?

  • DevArt
    DevArtMar 24, 2024

    Top 50 One-Liners JavaScript
    :- forn.fun/sh20raj/top-50-one-liners...

Add comment