Friday, March 4, 2016

ES6 and Babeljs

Introduction

In the implementation of control tool kit we will be using ES6 or ECMAScript6. As the code developed using ES6 is not compilable in browser, we need babeljs to compile it and run it in browser. The development stack discussed below.

What is ES6?

ES6 is ECMAScript 6. It is a scripting language specification created by a committee called TC39. Currently the JavaScript we use for development is basically following ES5. All the modern browsers has support for it with different JavaScript engines, like - V8 (in google chrome). For ES6, the browsers dose not has full support. So if we do code in ES6, browser compilers will through compile time (Syntax) error, as this version of ECMAScript has many new syntactical and implementation level changes, which we will discuss shortly. So, to overcome this and to use new features of ES6, we need some compiler which will take ES6 code as input and give us something browser compliable.

What is Transcompiler or Transpiler?

Transpiler is a tool or engine to compile one source code to another source code. To use ES6 now , we need to use some kind of transpiler to convert ES6 to something browser compliable(e.g ES5). There are several transpiler is market now, which facilitates us to use ES6 now . Babeljs is one such transpiler, which we will be focusing now.

What is Babel?

Babeljs is a transpiler to convert ES6 code to ES5. Babel supports pre and run time compilation. Pre compilation is for compiling our ES6 code to ES5 in the time of project build. For production environment pre compilation is preferable. Runtime compilation is straight forward process to compile your ES6 code to ES5 in the browser itself, which is time consuming for sure and not preferable for practical implementations.

How to convert ES6 to ES5-

As discussed above there are two ways to do it. Lets discuss preferable way first-

Per- compilation of ES6 code using Babeljs.

There is a npm module called babel, which we need to install in our app.

npm install babel

Then it's pretty straight forward to compile the ES6 code to current javasctipt code.

babel script.js

Babeljs also has gulp support. We can use gulp-babel to do the same using gulp build process.

First install it-

npm install --save-dev gulp-babel

In gulp file-

var gulp = require('gulp'); var babel = require('gulp-babel'); gulp.task('default', function () { return gulp.src('src/app.js') .pipe(babel()) .pipe(gulp.dest('dist')); });

It will compile app.js ES6 code files to vanilla JavaScript and put it in dist folder.

Now let's see, how the runtime compilation works. We need to add reference of browser.js in our web page from babel-code folder after npm installation of babel. This will basically convert all the scripts with type text/babel from ES6 to JavaScript (ES5).

<script src="node_modules/babel-core/browser.js"></script> <script type="text/babel"> class Test { test() { return "test"; } } var test = new Test; test.test(); </script>

But as discussed previously, it will make the application perform slowly.
That's all we need to know about babeljs for now.

ES6 Feature

ES6 gives us a true programming language flavor in javascript just like Java, C# and so on. We can utilize all the features like - class, inheritance, anonymous function, scoped variable, string template, destructuring, itaitarator, etc.

Class

More oop type approach than using prototype.

class Rectangle extends Shape {
constructor (id, x, y, width, height) {
super(id, x, y)
this.width = width
this.height = height
}
}
class Circle extends Shape {
constructor (id, x, y, radius) {
super(id, x, y)
this.radius = radius
}
}

Constant

Const variable declaration support

const PI = 3.141593

Arrows

Simplified anonymous function declaration

nums.forEach(v => {
if (v % 5 === 0)
fives.push(v)
})

Get-Set

Like modern language seter and geter method for properties.

class Rectangle {
constructor (width, height) {
this.width = width
this.height = height
}
set width (width) { this._width = width }
get width () { return this._width }
set height (height) { this._height = height }
get height () { return this._height }
get area () { return this.width * this.height }
}
var r = new Rectangle(50, 20)

Block-scoped variables

Variables are now scoped within a code block using let key word.

for (let i = 0; i < a.length; i++) {
let x = a[i]

}
for (let i = 0; i < b.length; i++) {
let y = b[i]

}

Default Parameter

function f (x, y = 7, z = 42) {
return x + y + z
}

Rest Parameter

'a' can take n number of params and keep it in array of params ,can be accessed by index.

function f (x, y, ...a) {
return (x + y) * a.length
}

New Built-In Methods

Helper methods to do searching , validation , verification with lesser code.

Object.assign(dst, src1, src2)
[ 1, 3, 4, 2 ].find(x => x > 3)
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4) // true
"hello".includes("ell") // true
"hello".includes("ell", 1) // true
"hello".includes("ell", 2) // false
Number.isNaN(42) === false
Number.isNaN(NaN) === true
Number.isFinite(Infinity) === false
Number.isFinite(-Infinity) === false
Number.isFinite(NaN) === false
Number.isFinite(123) === true
Number.isSafeInteger(42) === true
Number.isSafeInteger(9007199254740992) === false

String Interpolation

In build String tinplating. No more - str + val

var customer = { name: "Foo" }
message = `Hello ${customer.name}`

Property Shorthand

Smart way to declare {x:'x',y:'y'}

obj = { x, y }

Method notation

Smart way to declare {x:function(){}} as shown below

obj = {
foo (a, b) {
...
},
bar (x, y) {
...
},
*quux (x, y) {
...
}
}

Modules

Import and export modules just as importing name space.

// lib/math.js
export function sum (x, y) { return x + y }
export var pi = 3.141593

// someApp.js
import * as math from "lib/math"
console.log("2p = " + math.sum(math.pi, math.pi))

Map & Set

let m = new Map()
m.set("hello", 42)
m.set(s, 34)
m.get(s) === 34
m.size === 2
for (let [ key, val ] of m.entries())
console.log(key + " = " + val)

let s = new Set()
s.add("hello").add("goodbye").add("hello")
s.size === 2
s.has("hello") === true
for (let key of s.values()) // insertion order
console.log(key)

Promise

function msgAfterTimeout (msg, who, timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`${msg} Hello ${who}!`), timeout)
})
}
msgAfterTimeout("", "Foo", 100).then((msg) =>
msgAfterTimeout(msg, "Bar", 200)
).then((msg) => {
console.log(`done after 300ms:${msg}`)
})