Most ES6 features are either equal to or worse than their ES5 counterparts in terms of performance, some by orders of magnitude (!)
For example, `class` has particularly bad performance characteristics because under the hood it has to set an object's prototype on the fly (at least this is how Babel implements it) [1] and `super` is also slow due to prototype lookup [2].
If you need to make 30 million function calls per second, the ES5 counterparts aren't off limits. I hear the performance argument against early ES6 adoption from time to time. But the bottleneck when running javascript on the client or the server is almost never language constructs. Network requests, disk i/o, database queries...they're all going to take many thousands of times longer than a prototype lookup. We should write succinct code first, then optimize the slow parts.
Recently I've rewritten ES6 code to ES5, and have measured performance gains in doing so, not orders of magnitude faster but overall just a bit faster at everything. I think that even CoffeeScript does a better job at being succinct, and it transpiles to pretty fast ES5 code.
I'm curious to know in what scenario one may benefits from this kind of rewriting.
I guess your application:
- doesn't intensely manipulate the DOM (otherwise your js performance shouldn't really be the bottleneck).
- isn't easy to parallelize.
- or you already make massive usage of web workers and you still had issues.
No sarcasm at all, I've recently refactored in ES6 the code-base I'm working on, without noticing any performance issues, and we really gained in readability and maintainability doing so. That's why I really wonder what could lead me to do the exact opposite.
I think this is incorrect, some features are by definition slower. Take for example the iterable protocol, it will always be slower than a traditional for loop [1] because the spec mandates a prototype lookup and function call [2].
So far the only features that are actually fast are generators and the new data types (Map, Set, et al).
If you don't mind setting the function on instances at construct time, you can use ES2016 class properties:
class x {
a = wrapFunction(function() {})
}
This kind of use case is pretty well covered by ES2016 decorators as well (they're a bit more general as they act on property descriptors, not just values):
Neat, thanks! But we're working with the half-baked V8 ES6 support that is far from ES2016, unfortunately. However, it's interesting to see the support coming :-)
Since ES6 can be cleaner, many projects have switched to using it with a transpiler like babel. This project (if/when it works) could help move older code to the new standard for consistency.
Even otherwise, I'm sure this was a fun and challenging project for the author.
The I'm unlikely to use a tool like this is because I find the exercise of updating the codebase manually an important. Really understanding how and why ES6 syntax can clean up your code and how to use it properly.
Also, how many times do you get such a good opportunity to re-factor everything? This is a great excuse. Make it better, not just ES6ify.
Finally, improve your regex by updating certain elements of your code. A good example is moving all var statements to let across whole codebase, and then finding cases where you can 100% use const, and replacing all of those.
I've done this update recently (as have a lot of people) and it was great. If you do it right, you should delete more code than you add, and avoid numerous bugs by using const.
Person.prototype.getAge = function (birthYear) {
var age = 2015;
age -= birthYear;
return result;
// Do you mean return age?
};
Object.defineProperty(Person.prototype, 'age', {
get: function () {
return this.getAge();
// getAge function takes a required parameter.
}
});
Typed arrays, weak Maps, weak Sets, and let/const.
Now what I really wish to see in JavaScript are real Immutable Objects. Like, any variable declared with const makes that Object Immutable, not just preventing it from being reassigned. That, imo, would take JS to the next level. That and something like TypeScript/flow built in to native JS. It's do-able, and I see it happening way down the line, maybe es8/9 haha....
Trying some simple this-based class/instance-construction in the constructor leads to the whole thing failing:
var Person = function (name) {
console.log('This is the constructor.');
var _name = name;
this.getName = function() {
return _name;
};
};
Since this is 1 of the 2 patterns for creating classes, and the only one which supports encapsulation, it seems like a strange omission.
Especially so if the goal is to migrate "old" javascript to get it "modern". Migrating bleeding edge JS to even more bleeding edge JS hardly seems like a very worthwhile endeavour.
Sure, in the same way English can be improved by translating it to Chinese and then translating it back to English. As the The Presbyterian Church said in Star War The Backstroke of the West: "Do not want!"
Surely the compiler handles the case of anonymous functions referring to `this` or `arguments` and leaves them alone?
edit: the original issue[5] specifically notes that the anonymous function shouldn't refer to `this` and the corresponding commit has a test case for that, though it doesn't talk about `arguments` so that might break.
Unlikely, the same commit added it all, I can only assume the offline version behaves similarly (I haven't tested).
The compiling seems very inconsistent and fragile:
* it won't convert at all if a function literal is returned or assigned to a variable (but it will if the function literal is passed to an other function or for IIFE)
* it will generate an incorrect conversion in case the `this` is deref'd for a method call or (directly or indirectly) passed to an other function: these are OK (will not convert)
It's not like your JS won't run on ES6 browsers. That's the whole point of backwards compatibility. Besides, older features will probably have better performance as they have been tuned for years, compared to newer features.
People in the JS world should seriously drop the NIH syndrome and contribute to existing tools instead. The last thing we'd ever need is yet another framework/library/tool that's just a bit more than what's already existing.
I don't see this as a real benefit to update your code, but maybe as a learning tool to see how your code would be implemented using es6.
I like to take a wait-and-see on these language updates to see which parts get widespread adoption. I find the most important part at this point isn't the features, but having code that the majority of developers can understand.
Demo box felt claustrophobic. I pasted in code and nothing appeared on the other side. An error message would have been nice. Ah well, I'll probably check this out again after a while.
For example, `class` has particularly bad performance characteristics because under the hood it has to set an object's prototype on the fly (at least this is how Babel implements it) [1] and `super` is also slow due to prototype lookup [2].
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
[2] https://jsperf.com/es6-classes-super-es5-vs-transpiled/2