ECMAScript 6 specification and implementation is underway and promises to bring many of the features that you’ve learned about in the posts on Object JavaScript.
This post gives you an idea of what the code looks like in ECMAScript 6. This post doesn’t cover ever feature. But you will learn about how ECMAScript 6 relates to:
- Scope
- Arrow Functions and Lexical this
- Default Function Parameters
- Classes
- Inheritance
- Modules
- for-of
- Arrow functions
- Promises
I won’t come close to covering all the features. But you can get an idea of how ECMAScript 6 works to support the idea of Object JavaScript. Look to the references and to the specification for information about: Parameter handling, multiple return values, collections, destructuring, rest parameters & spread operator, iterators, array comprehension, and more.
Special thanks to Axel Rauschmayer for many of the snippets.
I found two great articles that I am pulling information from:
Scope
JavaScript variables are function-scoped (Object-JavaScript series reference: Scope, Namespaces, “use strict”). This means that, even if there are variables declared in a nested block, they are available throughout the function.
Today: function scope
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function orger (x,y) { | |
if (x > y) { | |
var tmp = x; | |
x = y; | |
y = tmp; | |
} | |
console.log(temp === x); | |
// true | |
return [x, y]; | |
} |
In the code, you see line 3 , var tmp = x;
where tmp is available outside its block.
EC6: block scope using let, const
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function order(x, y) { | |
if (x > y) | |
{ | |
let tmp = x; | |
x = y; | |
y = tmp; | |
} | |
console.log (tmp === x) | |
// reference error: tmp not defined | |
return [ x, y]; | |
} |
let
, which is like var
, except for the fact that it is block scoped instead of function scoped.
let
and const
behave similarly in the sense that both are block scoped, but with const
, the values are read-only and cannot be re-declared later on.
Arrow Functions and Lexical this
Linq uses the arrow (=>
) operator uses and expression called a lambda expression. In ECMAScript 6, there is the idea of arrow functions, which seems to me to be similar. It looks like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//today | |
let squares = [1, 2 , 3].map(function (x) { | |
return x * x | |
)); | |
// is simplified to | |
let squares = [1, 2, 3].mpa (x => x * x); |
In the post on Using the ‘this’ Keyword I described some of the issues around using this
in JavaScript. In ECMAScript 6, you can use the arrow function to peform a lexical this
. You can use the arrow function so do something similar to var that = this;
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function UiComponent { | |
let button = document.getElementById('#myButton'); | |
button.addEventListener('click', () => { | |
console.log('click'); | |
this.handleClick(); | |
}); | |
} |
Default Function Parameters
For those of you familiar with C# or TypeScript, you will instantly recognize the ide oa default parameters.
In ECMAScript 6 the default parameters are defined when the functions are defined.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function history(lang = "C", year = 1972) { | |
return lang + " was created around the year " + year; | |
} |
Classes
In object-oriented programming languages, a class is a representation of an object. It forms the blueprint, while an object is an instance of a class. With regard to JavaScript, it is a class-less programming language and everything is an object. Traditionally, we’ve used functions and prototypes to implement classes.
ECMAScript 6 implements classes with minimal class declaration syntax that can be extremely important to distinguish classes and functions.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Point { | |
constructor(x, y) { | |
this.x = x; | |
this.y = y; | |
} | |
toString() { | |
return '(' + this.x + ',' + this.y + ')'; | |
} | |
} |
Inheritance
In the post on Understanding Prototypes, Inheritance you learned about the messy job of inheritance in Object JavaScript. And it got a little cleaner in Inheritance Using Revealing Module Pattern. In ECMAScript 6, you can use the extends
keyword to derive from a parent class, then use the super
keyword to call the parent class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ColorPoint extends Point { | |
constructor(x, y, color) { | |
super(x, y); | |
this.color = color; | |
} | |
toString() { | |
return this.color + ' ' + super(); | |
} | |
} |
Modules
In programming languages, modules perform isolated discrete functions and are independent of one another. This helps to not only build reusable components across projects, but also keeps errors isolated to the parts related to the current project.
Lots of discussions in my blog about modules, such as Asynchronous Module Definition (AMD) I am a big fan.
You can name export
s to be used by other modules. For example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in lib/math.js | |
let notExported = 'abc'; | |
export function square(x) { | |
return x * x; | |
} | |
export const ONE_TWO_THREE = 123; | |
// in main1.js | |
import {square} from 'lib/math'; | |
console.log(square(3)); | |
// in main2.js | |
import as match from 'lib/math'; | |
console.log(math.square(3)); |
A default
provides a way to export a function. For example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in myFunc.js | |
export default function( /* … */) { | |
// … | |
} | |
// in main2.js | |
import myFunc from 'myFunc'; |
Or export default
a class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in MyClass.js | |
export default class { | |
// … | |
} | |
// in main2.js | |
import MyClass from 'MyClass' |
And there are more features on the way, such as:
- Rename imports.
- Module IDs are configurable (default: paths are relative to importing file.
- Programmatic (conditional) loading of modules.
- Module loading is configurable.
Object.assign
The Object.assign
works in a way similar to _.extend()
from Underscore.js, which copies all of the properties in the source objects over to the destination object, and return the destination object.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Mreges one object into another | |
class Point { | |
constructor(x, y) { | |
Object.assign(this, { x, y }); | |
} | |
} |
for-of
for-of
replaces for-in
and Array.prototype.forEach()
. It works for iterables. For example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// outputs elements not indices | |
let myArray = ['hello', 'world']; | |
for (let elem of myArray) { | |
console.log(elem); | |
} | |
/* output is | |
hello | |
world | |
*/ | |
// in ECMAScript 6 | |
// using the same array | |
for( let [index, elem] of myArray.entities()) { | |
console.log(index, elem); | |
} | |
/* output is | |
0 hello | |
1 world | |
*/ |
Promises
You learned about Promises in several posts:
- Asynchronous Programming Using Promises
- Promises for Asynchronous Operations Using jQuery
- Asynchronous JavaScript Promises Using Q
The ECMAScript 6 implementation will look familiar for the user of Q. If you are using jQuery, it will look a bit different. As a producer, you create a promise and send a result
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var promise = new Promise( | |
function (resolve, reject) { // (A) | |
// … | |
if ( /*…*/ ) { | |
resolve(value); // success | |
} else { | |
reject(reason); // failure | |
} | |
}); |
A promise is always in either one of three (mutually exclusive) states:
- Pending: the result hasn’t been computed, yet
- Fulfilled: the result was computed successfully
- Rejected: a failure occurred during computation
A promise is settled (the computation it represents has finished) if it is either fulfilled or rejected. A promise can only be settled once and then stays settled. Subsequent attempts to settle it have no effect.
As a consumer of promise
, you are notified of a fulfillment or a rejection via reactions – callbacks that you register with the method then()
:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
promise.then( | |
function (value) { /* fulfillment */ }, | |
function (reason) { /* rejection */ } | |
); |