Why Babel doesnt use javascript class when transpiling to ES2015? - javascript

I've recently been trying the online Babel transpiling tool, and I've noticed that when transpiling a class to ES2015, it doesnt use javascript class and creates var _createClass = function () {... boilerplate instead: Demo
Yet, the javascript class keyword has been added in ES2015. Source
The javascript class is used only when ticking ES2016.
Why is that?

I've noticed that when transpiling a class to ES2015, it doesnt use javascript class: https://babeljs.io/repl#?presets=es2015&…
You weren't transpiling to ES2015, you were transpiling from ES2015 to an older version. The ES2015 preset selects all the transformations that generate ES3/5 code for ES2015 stuff.
The javascript class is used only when ticking ES2016.
Yes, it keeps the class syntax and other features from ES2015 when you only transpile the ES2016 (or higher) stuff.

Yet, the javascript class keyword has been added in ES2015
Yes, the keyword was defined on ES2015 and class was already a reserved word before that, but the actual implementation is a different story. As #AshKander mentions in they comment, the point of using babel with a specific target is to get that code to work on all browsers that support such target.
List of reserved keywords (present and future)

Related

How does the browser know I'm targeting ES6?

I'm using Typescript and I recently changed the transpilation options to target ES6 instead of ES5.
I was using a certain syntax that had always worked fine under ES5, but after the target change, I started getting this error in the (Firefox) browser console:
Javascript ES6 TypeError: Class constructor Client cannot be invoked without 'new'
I changed the code to a suitable syntax for ES6, and this fixed the issue, but I don't understand how the browser would know to throw this error in the first place, because the exact same code worked before.
Does the javascript parser in browser scan other parts of the code base and see they they're using ES6, and then reject this line because it doesn't match the ES6 code elsewhere?
Javascript doesn't enter any particular "mode".
Likely what really happened is that you were declaring a class Client. That is ES6 syntax, and it comes with the special caveat that you must use new Client to instantiate it. Now, your compiler compiled this into a backwards-compatible function Client() .... Obviously, you can call a function without new. And that's what you were doing somewhere.
So, the compilation from class to function masked the error. But when leaving the class as class (because ES6 target mode does not need to dumb it down to a function), the browser was actually dealing with a class and raised that error.

nightwatch-cucumber ES6 --- nightwatch JS ES5

I've read that nightwatch does not support ES6. Fair enough.
However, the documentation for nightwatch-cucumber
Looks like it uses ES6 (arrow functions) on the steps it defines as examples.
My question is: Is it possible to use ES6 on the cucumber steps and ES5 on the page objects for nightwatch? Or should I stick to ES5 for everything?
Yes I was able to write my cucumber steps in ES6 and my page objects in ES5. However it might be better to stick to ES5 to have consistency + I did notice I would get some strange failures (rarely) when using:
Given('Go to Site', () => client.url('https://google.com'));

How to get rid of editor’s error for object.key

I have the following code that basically gets some JSON data, looks for the keys with "servergenre", and saves the results in an array.
This is a follow up of this question.
let result = [];
Object.keys(data).forEach( key => {
if(/servergenre/.test(key)){
result.push(data[key])
}
});
Even though the code is working correctly, in some editors it raises syntactic errors:
"key": unsolvable variable or type key
"=>": expression expected
"if( / server...": formal parameter name expected
")){": , expected
"});": statement expected
Here is an image to show you where the errors are:
As I said the code is working fine, I just need it to be fixed or another approach to get rid of the errors.
Furthermore, many compressors and minifiers do not support this bit of code. So I can’t minify it.
Thanks in advance.
ES2015, formerly known as ES6, is a more recent version of JavaScript, which introduces features such as the => syntax for functions you are using.
Not all features of ES2015 are fully supported in all browsers, so many people who use it pass it through a compiler (“transpiler”) first to convert it to ES5, which is supported by all browsers. Babel is one such transpiler. But if you are only targeting newer browsers, that would explain why the => syntax is working for you.
You just need to change your editor settings to understand that syntax. Exactly how you do that depends on what text editor you are using. It could be that your editor's built-in JavaScript mode doesn't know how to read ES2015 syntax, and you need to either upgrade your editor or install a third-party plugin that provides an updated error-checker. Or it could be that your editor supports both ES5 and ES2015, and it thinks you are trying to write your project only in ES5. In this case you just need to go to the settings and tell your editor that you mean for this project to use ES2015 (or ES2016, which is currently the most recent version).
Fat arrows are ES6 syntax. If that causes trouble, just write good old ES5 :
let result = [];
Object.keys(data).forEach( function(key) {
if(/servergenre/.test(key)){
result.push(data[key])
}
});

Transpiling class based web components with babel

I've a simple web component following the latest web components v1 class syntax, it works great in Chrome and Firefox/Edge (with a polyfill) but I'd like it to run in IE11 so I need to transpile the class. However running it through babel produces code that no longer works in any browser.
Is there any way to generate backwardly compatible web components with the class syntax or is there a preferred way to write web components for maximum compatibility?
Example code -
class TestElement extends HTMLElement {
connectedCallback(){
this.innerHTML = "<div>Testing</div>"
}
}
customElements.define('test-element', TestElement)
Error message when using transpiled code is -
Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
To compile Custom Element classes with Babel, you can use this plugin from Github.
It will use Reflect.construct() instead of new, which is not permitted with HTMLElement objects.
One solution is to use the native-shim available with this polyfill
https://github.com/webcomponents/custom-elements
It's not perfect though, would like to find a cleaner solution.

How can I use decorators today?

I see decorators being used today already in some javascript code. My question is really two fold.
First:
If decorators have not even been finalized how is it possible to use them in production code, today? Won't browser support be non-existent?
Second:
Given it is possible to use it today, as some open source projects would suggest, what's a typically recommended setup for getting decorators to work?
You're right, ES2016 decorators are not yet part of the spec. But it doesn't mean we can't use it today.
First let's take a step back and go over "what is a decorator". Decorators are simply wrappers that add behavior to an object. It's not a new concept in javascript (or programming in general), it's actually been around for a while...
Here's a basic example of a decorator that checks permissions:
function AuthorizationDecorator(protectedFunction) {
return function() {
if (user.isTrusted()) {
protectedFunction();
} else {
console.log('Hey! No cheating!');
}
}
}
Using it would look like this:
AuthorizationDecorator(save);
You see all we're doing is simply wrapping up some other function. You can even pass a function through multiple decorators each adding a piece of functionality or running some code.
You can even find some old articles explaining the decorator pattern in javascript.
Now that we understand decorators are actually something we (javascript community) were always able to do, it probably comes as no shock that really when we utilize ES2016 decorators today they are simply just being compiled down to ES5 code hence why you maintain browser compatibility. So for the time being it is simply syntactic sugar (some really sweet sugar I might add).
As for which compiler to use to convert your ES2016 code to ES5 code, you have some choices: Babel and Traceur are the most popular.
Here's further reading on Exploring ES2016 Decorators.
#Class decorators support can be enabled in Babel/Traceur
Babel:
$ babel --optional es7.decorators
Source: Exporing ES7 Decorators - Medium
Traceur:
traceurOptions: {
"annotations": true
}
#Property decorators are not supported
...and since each #Property provides a unique functionality, each requires a different approach to desugaring in ES6/7.
Here's how you use #Inject:
Typescript
exports class ExampleComponent {
constructor(#Inject(Http) http: Http) {
this.http = http;
}
}
ES 6/7
exports class ExampleComponent {
constructor(http) {
this.http = http;
}
static get parameters() {
return [[Http]];
}
}
Source: https://stackoverflow.com/a/34546344/290340
Update:
It looks like Babel changed the way decorators are configured and the article is out-of-date. Here's a link to the new approach.
In short; yes you can use #Class decorators in ES6/7; no property decorators aren't supported in ES6/7 so you'll have to use workarounds.
There are some solutions to use decorators:
babel - an es next to es5 compiler with support of decorators.
traceur - another es next to es5 compiler by google.
typescript - a typed superset of javascript language that supports decorators.
There are some difference how these tools transpile a "modern" javascript to an older one so you can explore it if needed as they have online playgrounds.

Categories

Resources