Hacker News new | past | comments | ask | show | jobs | submit login
Xto6 modernizes your JavaScript code (xto6.js.org)
87 points by atriix on Dec 15, 2015 | hide | past | favorite | 45 comments



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].

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

[2] https://jsperf.com/es6-classes-super-es5-vs-transpiled/2


FYI, when compiled with Babel 5's loose mode, the transpiled code is roughly similar to what you'd hand-write:

https://babeljs.io/repl/#?experimental=true&evaluate=true&lo...

I didn't test the performance impact though. Also it's still a mystery to me how to enable Loose mode in Babel 6.



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.


You should really qualify that with "transpiled ES6 features". Native implementations will not necessarily be slower.


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).

[1] https://jsperf.com/for-vs-for-of/2

[2] https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...


I always read you should usw loose mode if you can, which shouldnt have these Bad performance implications.


Always getting 'app.js:22 Uncaught TypeError: Cannot set property 'kind' of undefined' :-(

However, I doubt that I would use it - most of the 'modernizations' are really dependent on the context of each change and require some tweaking.

For instance, ES6 classes do not allow for inline computed methods:

  const x = function () {};

  x.prototype.a = wrapFunction(function(){});
--- this is impossible: ---

  class x {
     a() wrapFunction(function(){}); // invalid :-(
  }
So we're still required to use the explicit prototype way of declaring the class.

Then you can't just rewrite all methods to arrow functions because they don't have prototypes, even when they're really tempting:

  var x = function () {};
  x.prototype.a = <foo>;
--->

  var x = () => {};
  x.prototype.a = <foo>; // cannot set a of undefined
...

$0.02


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):

    class x {
      @functionWrapper
      a() {}
    }


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 :-)


Your working javascript can now be transformed into slower, more incompatible code that might not work! Yaaaaaaaay.


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.

So, more like this. And congrats on release.


I agree it is a fun project.

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.


Wow, the example is atrocious,

  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.
    }
  });


Javascript sure got more features, but how many should Crockford add to "the good parts"? If you ask me, only generators.


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....


Object.freeze?


Arrow functions that don't rebind this would also be on the list for me, as would be block-scoped variables.


According to this recent talk, not many, and he would even take away features from The Good Parts:

The Better Parts by Douglas Crockford: https://youtu.be/Ji6NHEnNHcA


constants, string templates, async/await, decorators


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.


Could this be used to improve current ES5 codebases by converting to ES6 and then use Babel to convert back to (improved?) ES5?


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!"


Watch out for lexical binding with arrow functions. It could lead to some nasty bugs if you blindly transpile your old code.


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.

[5] https://github.com/mohebifar/xto6/issues/5


Perhaps it's fixed on the master branch but it's broken on the websites live transpile thing (which is where I tested it).


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)

    (function () { this; })();
    (function () { this.foo; })();
    (function () { this.bar + 1; })();
but these are not ok (will convert to incorrect code):

    (function () { this.foo(); })();
    (function () { foo(this); })();
    (function () { foo(this.bar); })();


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.

http://www.isaacchansky.me/days-since-last-new-js-framework/



Ahaha, there's this one which goes even further: only uses "[]()!+" https://github.com/aemkei/jsfuck


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.


i would like a es6 to es3 compiler. When working with legacy devices it's a real mess, especially when you are used to sometimes use console.log..


can someone explain where "result" comes from in their examples?


It's neat to see a competitor to babel, but man that colour scheme is suspiciously similar.


> xto6 transpiles your ES5 code to ES6. It does exactly the opposite of what other transpilers do (like babel and traceur).


Babel is ES6 to ES5 right? This seems to target a different audience. Namely moving your ES5 codebase to ES6 automatically.

Also I think the similarity in color scheme is very intentional. As this seems like a wink towards babel, being an anti-babel.


Yes, in fact it looks a lot like a preparing step towards babel: convert ES5 codebase to ES6, then use babel so it still runs on ES5 browsers.


Yellow and grey are the colours on the JS logo, I'm assuming that's why both Babel and xto6 use it.


> It's neat to see a competitor to babel, but man that colour scheme is suspiciously similar.

It's more like a reverse Babel. Babel does 6 to 5 , this does 5 to 6.


the color scheme is monokai, used by the ace editor (others as well)


Parent meant the yellow/black color scheme of the webpage, which are the colors Babel uses for its branding too.


probably because JS logo has also similar colors: https://raw.githubusercontent.com/voodootikigod/logo.js/mast...




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: