Skip to content

Instantly share code, notes, and snippets.

@joewalnes
Last active August 29, 2015 14:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joewalnes/9c4f10f9802a64603f33 to your computer and use it in GitHub Desktop.
Save joewalnes/9c4f10f9802a64603f33 to your computer and use it in GitHub Desktop.
with great regret
// Let's look at a snippet from a React example here: http://facebook.github.io/react/
// -----------------------------
// This is how you build the React virtual DOM with plain JavaScript.
return (
React.DOM.div(null,
React.DOM.h3(null, "TODO"),
TodoList({items:this.state.items}),
React.DOM.form({onSubmit:this.handleSubmit},
React.DOM.input({onChange:this.onChange, value:this.state.text}),
React.DOM.button(null, 'Add #' + (this.state.items.length + 1))
)
)
);
// Not too bad. But all those React.DOM prefixes are fugly and clutter up the code.
// -----------------------------
// One such solution is the React JSX compiler which allows embedding of tags in JavaScript.
// Like this:
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<input onChange={this.onChange} value={this.state.text} />
<button>{'Add #' + (this.state.items.length + 1)}</button>
</form>
</div>
);
// Clever! It's definitely more compact.
// But introducing a compiler increases the infinitely increases the complexity of building your app
// (Literally infinitely: Without JSX you need zero build steps, with it you need to introduce some
// kind of build system). I don't want this complexity.
// And it makes debugging harder (try pasting JSX code in the chrome console or setting breakpoints).
// JavaScript source maps may help one day, but we're not there yet.
// And finally, the syntax is alien to most editors, syntax highlighters etc. Don't expect
// auto-completion to work in WebStorm. Look at how confused GitHub is with the colors in the
// above code.
// -----------------------------
// There's another way.
// Let's stick with JavaScript and use some the with() statment.
with(React.DOM) {
return (
div(null,
h3(null, "TODO"),
TodoList({items:this.state.items}),
form({onSubmit:this.handleSubmit},
input({onChange:this.onChange, value:this.state.text}),
button(null, 'Add #' + (this.state.items.length + 1))
)
)
);
}
// See.... That tiny with() wrapper made the rest of the code block readable again. Less clutter, more
// expressive.
// And no need for silly build tools, source maps, etc. Just keep on coding in plain old JavaScript.
// -----------------------------
// But.... isn't with() the spawn of satan? Why else would they deprecate it?
// I know there's a gazillion blog posts out there saying how
// bad it is, but really there's only 1 or 2 and the rest are re-quoting each other.
// Firstly, even if you never explicitly write with(...) {...}, you are in fact using an implicit
// with(window) { ... } in every single function you write. Every one!
// (or with(global) {...} in Node)
// Seriously - we have an implicit global object everywhere. Even if you don't use with(), you're
// still subject to all the same pitfalls.
// To all those who rally against with(), that's fine.
// But don't let me ever catch you calling setTimeout(), encodeURIComponent(),
// document.getElementById() or new XMLHttpRequest() in your code.
// You should be using window.setTimeout(), window.encodeURIComponent(),
// window.document.getElementById() and new window.XMLHttpRequest().
// Don't like that? Well you could rely on the implicit with(window) then.
// See, all with() does is temporarily allow you to reduce the scope of the global namespace.
// Reducing scope is a good thing.
// No longer are we tempted to throw all our variables, functions, objects into the global
// namespace. We can throw them into a more meaningful context and switch to that when it
// makes sense.
// My point I'm making is that by avoiding with(), we're not really avoiding it at all
// as we have to use it implicitly anyway and inherit all the pitfalls on the global
// object. It's the elephant in the room.
// EcmaScript 5 introduced 'use strict' which fixed up one of JavaScript's biggest
// sources of mistakes - accidentally assigning a variable without declaring it with
// var.
// In one fell swoop, this fixed every single issue with with().
// 'use strict' should have been with()'s savior, making it finally safe to use
// - except it then turned round and pulled a Red Wedding, killing it.
// We lost. You can 'use strict' and never again experience the simplicity and joy
// of reducing the global scope. Or be a Luddite and stick with with() and just
// be careful with your vars. Which we've all had to do for years anyway thanks
// to that big implicit with(window) that's always forced on us.
// Viva la 'use strict-but-allow-with';
// Don't get angry... smile!
// http://codepen.io/joewalnes/pen/wEhdn :) <-- uses with() to improve code clarity
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment