Last active
August 29, 2015 14:01
-
-
Save joewalnes/9c4f10f9802a64603f33 to your computer and use it in GitHub Desktop.
with great regret
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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