Anyway, we use as much ES6 as Node 4 allows at work. Transpiling on the server never made much sense to me. I also used to sprinkle the fat-arrow syntax everywhere just because it looked nicer than anonymous functions, until I realized it prevented V8 from doing optimization, so I went back to function until that's sorted out (I don't like writing code that refers to `this` and never require binding, so while the syntax of => is concise, it is rarely used as a Function.bind replacement). Pretty much went through the same experience with template strings. Generator functions are great.
I'm not a fan of the class keyword either, but to each their own. I think it obscures understanding of modules and prototypes just so that ex-Class-based OOP programmers can feel comfortable in JS, and I fear the quagmire of excessive inheritance and class extension that will follow with their code.
Transpiling on the fly on the server is even more painless than for the frontend:
- Require babel-core/register (as of Babel 6)
- Require your server entry point ES6 file.
- Done.
Everything just seems to work, no need for sourcemaps or anything; line numbers, error reporting, non-ES6 modules, everything Just Works. Haven't had a single issue since starting to do this 4 months ago (knock on wood). Highly recommended!
It's not that I don't know how to set it up or use it, I just trust a future V8 implementation enough to wait for it over using a shim. I've also become a bit allergic to dependencies :P.
I do trust that it works, and if I were working on a big project that would be hard to refactor for a major language change, or if I were working on the front-end where the available features are up to question based on client, I would definitely use babel. We have a lot of older code like that where I wish we had used babel years back.
In my case our backend is distributed across dozens of small (usually <400 line) packages so if a really nice ES2015 or 2016 feature becomes available the effort to refactor or rewrite will be measured in hours or days, not weeks or months.
Additionally, if you're using tape[1] for testing, I implemented a useful feature not too long ago to allow the preloading of modules[2] so you can run something like babel-register before your tests are run, effectively plugging in JIT-like support for your tests. (End shameless plug.)
The babel documentation says it's a bad idea to do this in production, so I'm thinking of using webpack to transpile then entire back-end to one ES5 file. Do you know enough about this situation to tell me if this is a bad idea or not? Because obviously your approach would be 'simpler'.
Edit: An additional reason to transpile to ES5 is that on the whole much of the ES6 support is not very performant yet. While this might not matter for incidental uses of, say, template strings, it might become noticeable for an entire project. Or is that a clear case of premature optimization?
There's no difference in compiling to ES5 versus hooking into the module loading mechanism to compile on the fly, in terms of the end-result. The only practical difference is that precompiling means your modules will load faster the first time, but there will be no difference for subsequent loads since modules are cached. I'm guessing the caveat for running something like babel-register in production is the first-load performance penalty, as well as having less control over the compilation process. However, if you are ok with configuring babel through .babelrc files alone, and you're ok with the first-load performance penalty, I don't see what it'd be any worse than precompiling to ES5. (There may be subtle differences in debugging due to the lack of source maps, but I don't know enough to comment on that with any degree of certainty.)
That's informative, thanks. At least I have something to look into, and a quick search indicates that source maps are not even necessary in this approach!
That being said I've used in production for quite a while, but the memory foot print is a lot higher. I'd recommend compiling to a separate file for production.
I recently put in the pull request to suggest not using register in production just as babel-node is not recommended.
> I'm not a fan of the class keyword either, but to each their own. I think it obscures understanding of modules and prototypes just so that ex-Class-based OOP programmers can feel comfortable in JS
I couldn't agree more. Classes were implemented so that JS haters could write syntax they wanted to and not to improve the language per say. Seems like JS is entering an age of cruft.
While I am also not a fan of the class keyword, I'd argue that we already had that age of cruft. For quite a few years (past decade?) practically every book on JS would start with the author building their own version of inheritance, and then relying on it throughout the rest of the book.
It's only in the last few years that the majority have stopped trying to recreate Java in JS. (I don't think the majority of PRACTITIONERS were doing this, but the majority of INSTRUCTORS were, causing a lasting problem until enough people willing/able to teach were grown within the community.
Agreed. I think JS is quite a broken language that should probably be replaced. It won't be, but it probably should. I know Google thinks Dart could be that language but they're not even trying to put the VM into Chrome, so it's just another replacement that needs to be compiled.
I was complaining about some JS stuff (particularly the required writing of "use strict") in the #nodejs freenode irc chat the other day and someone asked me a way to help solve these issues without breaking 50 year old code. Thinking about it, I think a good attempt would be to create an HTML meta tag that would tell the browser to parse all JS in strict mode. Maybe there's something already out there. This is already possible in nodejs, but browser side I think it could be a big help in moving things forward.
Isn't that basically what we did with doctypes? HTML has a lot of similar issues and it has slowly managed to move forward. The real benefit was not having to mix old and new code and getting rid of all the quirks by requiring you specify that you want them if you want that old doc to work.
JavaScript could get to the same place just be letting you specify a different language in the script tag.
The big question is how we support legacy browsers for a time because many won't support the new keywords.
A script type could work too. Either way, there would be some indicator of how the JS VM could parse the code. It's true you could get other languages into HTML this way as well, but the trick is that the browser needs to support the VM, which can be done natively or through a browser plugin/extension. Google tried this for a Dart VM (sidenote: there is no TypeScript VM from Microsoft that I'm aware of) into Chrome but discussions led away from that idea, and now Dart compiles to JS instead. A <meta> tag in <head> would eliminate <script type="application/sjavascript"></script>, <script type="application/sjavascript"></script>, etc. Though providing an either/or situation would be optimal too to allow a mixed script types for older libraries.
> While I am also not a fan of the class keyword, I'd argue that we already had that age of cruft. For quite a few years (past decade?) practically every book on JS would start with the author building their own version of inheritance, and then relying on it throughout the rest of the book.
This, right here. The class keyword is unfortunate, but at least it ends the useless meta discussion of "how to implement classes" by simply providing some sugar over the RightWayToDoIt(tm). (According to those in the know – whatever, I don't care for classes.)
> Unlike var, let and const statements are not hoisted to the top of their enclosing scope.
No, let is hoisted to the top of the enclosing scope [1] ("temporal dead zone" notwithstanding). let, however, is not hoisted to the top of the enclosing function.
I'd say that makes you technically correct, but practically speaking, if using let before it's declared (assigned?), this temporal dead zone, results in an error, it's pretty much not hoisted in the way that most of us think of it.
Or is there a use case that I'm not aware of where the hoisting is beneficial despite the temporal dead zone?
Interesting. This kind of stuff makes me want to dive into the details of these kinds of choices, as I regularly wonder why languages designed are a certain way.
I love how concise this is an handles a lot of "Gotchas" when working with ES6, but can we call a spade a spade and NOT call this a "cheatsheet?"
I always imagine cheatsheets to be just that; something I can render on one sheet of paper. Printing the entire raw README text would take 4 pages (2 sheets, front and back).
I think it would be better titled, "ES6 best practices" since I think that's a more accurate description of what it is.
One minor quibble. I was bothered by the misuse of the words "lexical" and "interpolate". The lexical value of the keyword "this " is the string "this". Then, you might translate between two technologies such as CommonJS and ES6 but interpolating between them implies filling in missing data by averaging known values. Granted this word is commonly abused. Sorry this is a bit pedantic but these corrections would improve the document, IMO.
The only thing from this list of new ES6 idioms that doesn't sit comfortably with me is the short-hand for creating classes. I remember being kind of blown away way back in the day with the prototypical/functional nature of Javascript and how you could wrangle something into being that behaved in an object-oriented manner just like other languages that had explicit class declaration and object instantiation.
Part of me feels that obscuring Javascript's roots in this respect is very un-Javascript-y. What think ye?
Coming from Ruby, loving template literals, feel right at home with them, I wish even C could have them (if that makes any sense!).
I think the cheatsheet does a great job of summarizing what makes me uncomfortable with es6 classes:
>"...the syntax for creating classes in ES6 obscures how implementation and prototypes work under the hood..."
Yes, it's great for if you're uncomfortable with prototypal inheritance and the "javascript way of doing things" (I'll maybe summarize that as composition over inheritance, mixins, knowing how to use call/apply etc.), but at the end of the day I'm worried it might be a crutch. Specifically, it might create the situation where a javascript noob might use es6 classes and never bother to learn how the prototypal chain works or all the myriad options available for mocking classes and OO behavior. That being said, maybe that's a shitty argument. When you have more tools in the toolbox there's always the option for someone picking the wrong tool. Does that mean you take the tool out? Or leave it because it is really useful when you know when to use it correctly. I imagine the latter.
If "un-JavaScript-y" were a bad thing... JS is not a particularly pure, or well-designed, language, so we should not treat it religiously.
Personally, I love ES6 for fixing many JS pain points (yes, hacky class-like object constructors are among them). If it is against it's history - so be it!
Prototype inheritance is fairly hard to reason about and fairly verbose to set up correctly. And if we aren't supposed to avoid inheritance that applies equally to prototype inheritance as well. Prototype inheritance allows even crazier inheritance situations.
I don't think it's reasonable to eliminate inheritance (it's very useful when it's needed) but restricting it down from what Javascript currently provides natively is a good thing.
I think it's un-Javascript-y as well, and I consider that a good thing. I don't think javascript is a particularly well designed language. (I mean, it's great considering its origins, but still)
If I could avoid writing javascript I would, but unfortunately, you have to write javascript to do anything inside a browser. I can't wait until class {} gets widespread browser support. I know compile-to-javascript languages are a thing, and I use them, but in my experience, you can't get away with not knowing javascript.
It was really hard to make truly private properties that couldn't be leaked in some way without WeakMap. If you don't need foolproof leakage, Symbols are a more convenient way to get most of the benefits of private properties. This is intentional: as I recall, the committee realized that WeakMap wasn't the most ergonomic solution and created Symbols as a more convenient, though less ironclad, alternative.
Additionally, symbols would have provided a neat way to implement private (and privately shared) properties, if they hadn't decided on adding the `getOwnPropertySymbols` function[1]. Bummer.
This cheatsheet is wrong about ES2015 modules. They don't define how module loading works, that's still being worked on [0]. ES2015 just defined the syntax.
Yes, in most cases. As always, the pro way to do it is to examine the browser statistics for your target market, decide which browsers you will/won't support, and build and test for those browsers. If you don't want to go to all that effort for your smaller project, the bottom line is that most developers today end up targeting ES5.
Less and less people are using CoffeeScript due to ECMA2015/ES6 being released with the large majority of functionality that CoffeeScript was created for.
You're probably better off just switching to ES6, but that's just my opinion.
"Require" is the reason why we now have a module for just about anything in Node.JS. I even think Kevin Dangoor or whoever invented it should get the Nobel prize. But then the ES committee choose to use paradigms from year 1970. I cry every time someone use import instead of require in JS because they miss out why globals are bad, modularity is good, and the JS API philosophy (super simple objects with (prototype) methods).
I'm not sure I understand. ES6 modules are basically equivalent to "require". `import foo from "foo";` is the same as `var foo = require("foo");`
Yes, it was Kevin Dangoor who started the CommonJS (originally "ServerJS") project and led many of the discussions. Kris Kowal and many others were instrumental as well. This is probably the pivotal mailing list thread for what became CommonJS modules: https://groups.google.com/forum/#!topic/commonjs/Gr72Bc8Twzc
The main technical difference is that you can not have scoped imports.
The main impact though, is that many will use a hammer on screws, meaning; people used to "other tools", can now do so (ES6: import, class, etc). While require teaches you to use the electrical screwdriver.
Are you saying you can't do function-scoped imports ("require" inside a function)? I rarely see that used and it's not available in any other language I can think of.
Yes. It makes things so much simpler. Your program do not have to be complex! It can exist entirely of functions that do not depend on their outer scope. You can basically change everything around them and the function will still work the same. And you do not have to look outside the function to understand what it does. You only have to know about the standard objects witch in JavaScript (ES5) is Math, Date, JSON and Error. Everything else is "required" when needed.
That's still true but on the module level. If your module is so large that it's hard to keep track of the imports/requires then you should probably split the module up.
I really don't think require-ing within individual functions is a common or good practice. Can you point me to an open source project that does that?
A module is already scoped in node.js. It would be nice to have scoped require in the browser too, instead of just global import.
Splitting up a program, or module, into (more) modules does not make it simpler, rather contrary, it makes it more complex! Unless it's a fully decoupled abstraction reusable in other projects.
An example of require-ing within individual functions: A function to send notifications to e-mail or SMS ... It makes more sense to require the SMTP or SMS module in those functions, then somewhere else.
This will likely get downvoted - but I have just realized how much I was underestimating the privilege of developing apps in Dart instead of JavaScript. Dart had none of the mentioned idiosyncrasies from day one, all the features, and has a lot of other stuff (like async/await, yield, mixins, etc) to offer. Its tooling is very simple and powerful, and the overall experience is really nice - when there is a problem, it's always in the logic of my code, and not things like some weird implicit conversions that are so common in JS land. I almost forgot how terrible JS is...
I'm all in on ES6 when it's practical or allowed. Arrow functions are wonderful, I love destructuring assignment, const and let, and considering that some projects I work on involve a lot of async stuff, I'm close to just giving in and using ES7's async/await functionality.
But most of the time this is in the context of Node.js development, and in every case I use Babel.js to turn the end result into ES5 code.
I'm perfectly comfortable with using ES5, because as a freelancer/contractor I often have to do so. But I really miss the ES6 stuff and the more I use it, the more time it takes me to 'switch' to a mindset where I'm only allowed to use ES5 functionality.
Nonetheless, it strikes me as really odd to actively prefer ES5. Having worked with Ruby and Python (among others), ES5 feels limiting for no good reason. The only rationale I can think of for prefering ES5 is nostalgia.
Could you elaborate why you don't like the 'perl/python' style changes? Because I truly do not understand why one would choose to limit oneself to things like .bind(this) instead of the different forms of arrow functions that make functional-like programming so much easier. And I've found that the best part of JS is that it's decently functional.
Edit: I would agree when it comes to the new 'class' keyword though. I'm not a fan of that.
> Could you elaborate why you don't like the 'perl/python' style changes?
It's really just a style preference. I enjoy the "look" of C-family code.
>why one would choose to limit oneself to things like .bind(this)
I know 'this' is a source of pain for a lot of people. For me, I see it a source of flexibility. I've found the ability to control the context at will to be a huge benefit. It's a feature I miss when I'm writing in other languages.
> For me, I see it a source of flexibility. I've found the ability to control the context at will to be a huge benefit. It's a feature I miss when I'm writing in other languages.
But that's why you can still use the regular functions... I don't quite understand how having the added option of a more concise syntax with automatic binding to the surrounding context is less flexible. I often find myself using the regular function declarations to differentiate between different sorts of functions. The arrow notation is opt-in.
Or is your issue that when you work with other people's codebases, you have no option to opt-out?
Having used ES7 async/await through Babel extensively for some highly asynchronous code, I can say that it feels much better than using Promises alone, even better than using ES6 generators + a runner (especially since async/await meshes so well with ES6 classes).
The only fear I have is that the spec might still change, which is not the case for ES6 features. Do you think my fears are unfounded? Because I'd love to use ES7 for my back-end projects where all database interaction, and by extension a large part of my codebase, relies on promises...
Webpack/browserify remove/polyfill most of the ES6 syntax so it is backwards compatible for browsers. Server side you just need to be aware of your engine's support of ES6.
The extra syntax around arguments (defaults and rest) is useful. ES5 does support function overload, but often ends up some hard to read hacks. Libraries commonly have only a few functions, but the functions have flexible signatures. So the first thing you see when trying to read their source is a jumble of argument parsing.
That said, ES6 can end up with some poor performance. For example, template literals are almost 10x slower than just plain string concatenation. But if you are concerned with performance, writing JS may not the be the best choice.
Not at work, but I use either ES6 or Typescript personally.
"All of the syntactic sugar stuff changes the look and feel of the language too much for my tastes."
I think it brings it into line with how the language is being used in production these days. Modules, generators etc make the language more beautiful, powerful and easier to maintain.
>>> Not at work, but I use either ES6 or Typescript personally.
Not a JS developer, but most of my friends who are have been transitioning to Typescript. The road is bumpy, but they say once you get some syntax stuff down, you're good.
TypeScript is very nice. The one main problem it has is lack of type definitions for third-party modules, some developers find having to "waste time" writing those defs themselves to be quite bothersome.
Typescript gives you an "out" to type checking using the any type. Additionally, most libraries really worth using have .d.ts files floating around the internet somewhere, in DefinitelyTyped or otherwise.
That's all true. It's a chicken-and-egg problem there, though. I've seen several arguments that the language is not worth looking into until more typings become available, and of course those naysayers are not going to write the missing typings.
Writing ES6 at work, turned into ES5 by Babel. I don't want to write "var self = this" ever again. Also, quite a few Node modules are ES6, and we use NPM for managing our frontend JS packages.
Using ES6 here most of the time as well, there's very few reasons not to these days. Some of the changes may only be syntactic sugar but you very quickly find yourself not wanting to go back.
I prefer ES6/ES2015 (currently via Babel, and considering TypeScript). The let keyword and arrow functions in particular make it a much more pleasant language to work with than plain JS. It's now competitive with CoffeeScript, but with more coherent and predictable parsing rules.
I'm fully using es6 for most of projects now. Started about 2 months ago and will make all new projects I have with it. Import/export, destructuring, templates, string interpolation.. it just cuts down on alot of the cruft (imo).
I'm still writing ES5 at work, but I've fully embraced ES6 (and bits of ES7) for personal projects. I love it and it's a major improvement to the language IMO.
Anyway, we use as much ES6 as Node 4 allows at work. Transpiling on the server never made much sense to me. I also used to sprinkle the fat-arrow syntax everywhere just because it looked nicer than anonymous functions, until I realized it prevented V8 from doing optimization, so I went back to function until that's sorted out (I don't like writing code that refers to `this` and never require binding, so while the syntax of => is concise, it is rarely used as a Function.bind replacement). Pretty much went through the same experience with template strings. Generator functions are great.
I'm not a fan of the class keyword either, but to each their own. I think it obscures understanding of modules and prototypes just so that ex-Class-based OOP programmers can feel comfortable in JS, and I fear the quagmire of excessive inheritance and class extension that will follow with their code.