The purpose of this is not to be an exhaustive list or a reference for ES6 features. This is intended to share the interesting ideas that are coming down the pipeline and to explore their intentions.
- String methods
- Variable type declarations
- Object features
- Function features
- Classes
- Working Interatively
- Promises
- Modules
- Other neat new features
- References
String.includes() // Anywhere within string
String.startsWith() // does it start with ...
String.endsWith() // does it end with ...
var
versus let
: let
is not the new var
. This has been said by many of the leading engineers within our community. let
was not intended to replace var
, but to complement it when block scope is important.
/**********************
* Old way: IIFE were needed to "snapshot" values at time of iteration
*/
for (var i = 0; i < arr.length; i++) {
(asyncFunction(arr[i], function callback(error, data) {
arr[i] = data.value;
}(i)); // This is necessary to capture the value of i at iteration
}
/**********************
* ES6 way
*
* With let, the value at iteration is preserved since
* a new i is created for each cycle
*/
for (let i = 0; i < arr.length; i++) {
asyncFunction(arr[i], function callback(error, data) {
arr[i] = data.value;
};
}
// Be aware: access a let before it's initialized errs out
if (true) {
console.log(name); // ReferenceError!
let name = 'Justin';
} else {
let name = 'James';
}
/**********************
* Old way
*/
var PI = 3.14;
PI = 7; // altered
/**********************
* ES6 way
*/
const PI = 3.14;
PI = 7; // throws error
function (greeting, name) {
// properties and method are placed without keys
var obj = {
greeting,
name,
sayHello () {
console.log(greeting + ', ' + name + '!');
}
}
return obj;
};
Destructuring works in parameters as well as var
s and let
s. Parameters are the most interesting to me
/**********************
* Old way
*/
function func(obj) {
// Manually destructure object into vars
var color: obj.color,
size: obj.size;
console.log(color); // "red"
console.log(size); // "large"
}
func({
color: "red",
size: "large",
quantity: 5
});
/**********************
* ES6 way
*/
function func({color, size}) {
console.log(color); // "red"
console.log(size); // "large"
}
func({
color: "red",
size: "large",
quantity: 5
});
/**********************
* Old way
*/
function func(type, color, size) {
var type = type || "t-shirt",
color = color || "black",
size = size || "large";
console.log(type); // "hoodie"
console.log(color); // "red"
console.log(size); // "large"
}
func("hoodie", null); // for any falsey value, the default will be assigned
/**********************
* ES6 way
*/
function func(type = "t-shirt", color = "black", size = "large") {
console.log(type); // "hoodie"
console.log(color); // null <-- surprised?
console.log(size); // large
}
func("hoodie", null); // only the absence of a value will set a default
/**********************
* Old way
*/
function func(user) {
var i = 1; // skip zeroth
// Have to access the arguments function to grab the unknown items
// Have to skip zeroth index to not iterate over the user parameter
for (i; i < arguments.length; i++) {
console.log(arguments[i]); // "SD9G876S98FG", "S9DF7SD98F7", "SDS0G87H8977H"
}
}
func("jlowery", "SD9G876S98FG", "S9DF7SD98F7", "SDS0G87H8977H");
/**********************
* ES6 way
*/
function func(user, ...items) {
for (let i = 0; i < items.length; i++) {
console.log(items[i]); // "SD9G876S98FG", "S9DF7SD98F7", "SDS0G87H8977H"
}
}
func("jlowery", "SD9G876S98FG", "S9DF7SD98F7", "SDS0G87H8977H");
var addTwo = (a, b) => a + b;
addTwo(2, 4); // 6
/**********************
* What's interesting is ...
*/
var api = {
el: document.getElementById('listItem'),
bindListener: () => {
this.el.addEventListener('click', () => {
this.clickAction(el); // `this` is api
});
},
clickAction: (el) => {
// logic
}
};
/**********************
* ... replaces ...
*/
var api = {
el: document.getElementById('listItem'),
bindListener: function () {
var that = this;
this.el.addEventListener('click', function () {
that.clickAction(el); // `that` is api because `this` would be global
});
},
clickAction: function (el) {
// logic
}
};
// There's more to arrow functions than what's above, so go explore.
/**********************
* Realy old way: the constructor/prototype pattern
*/
function Mammal () {
this.gestation = 'placental';
this.food_source = 'mammaries';
}
Mammal.prototype.gestation = function () {
console.log('Gestation is ' + this.gestation);
}
Mammal.prototype.feed = function () {
console.log('Feeding happens through the ' + this.food_source);
}
var cat = new Mammal('placental', 'mammaries');
/**********************
* Better new'ish way: Object.create() and behavior delegation
*/
var actions = {
init: function (gestation, food_source) {
this.gestation = gestation;
this.food_source = food_source;
},
gestation: function () {
console.log('Gestation is ' + this.gestation);
},
feed: function () {
console.log('Feeding happens through the ' + this.food_source);
}
};
var Cat = Object.create(actions);
Cat.init('placental', 'mammaries');
/**********************
* ES6 way: Classes (somewhat contraversial)
*/
class Mammal {
constuctor(gestation, food_source) {
this.gestation = gestation;
this.food_source = food_source;
}
gestation() {
console.log('Gestation is ' + this.gestation);
}
feed() {
console.log('Feeding happens through the ' + this.food_source);
}
}
var cat = new Mammal('placental', 'mammaries');
// Using the Mammel class above
class Dog extends Mammal {
vocalize() {
console.log('bark');
}
}
// Create iterator
var iteratorMachine = function (arr) {
var i = 0;
return {
callNext: function () {
return {
value: arr[i++],
done: i >= arr.length ? true : false;
}
}
}
};
/**********************
* Old way
*/
var oldIterate = iteratorMachine([1, 2, 3]);
oldIterate.callNext(); // { value: 1, done: false }
oldIterate.callNext(); // { value: 2, done: false }
oldIterate.callNext(); // { value: 3, done: false }
oldIterate.callNext(); // { value: undefined, done: true }
oldIterate.callNext(); // will keep going and going
/**********************
* ES6 way
*/
var es6Iterate = iteratorMachine([1, 2, 3]);
for (let item of es6Iterate) {
console.log(item);
}
// for-in will print out the value property of the returned object
$ 1
$ 2
$ 3
// for-in stops when the done property is true
function *myGenerator(arr) {
for (let i = 0; i < arr.length; i++) {
yeild arr[i];
}
}
var iterator = myGenerator([1, 2, 3]);
for (let item in iterator) {
console.log(item);
}
$ 1
$ 2
$ 3
function asyncRequest(url, verb) {
return new Promise(
function (resolve, reject) {
request(verb, url, function (error, response, body) {
if (request.statusCode === 200) {
// Success
resolve(response);
} else {
// error
reject(new Error(response));
}
}
});
}
asyncRequest('http://paypal.com/users/profile', 'GET').
then(
// Success method
function (response) {
console.log(response);
},
// Error method
function (response) {
console.log(response);
}
);
/**********************
* Old way: AMD
*/
require('myComponent', function (myComponent) {
myComonent.init();
});
/**********************
* ES6 way: Modules
*/
import myComponent from 'lib/myComponent';
myComponent.init();
- Map, set, weakmap, weakset
- Module loaders
- Proxies
- Template strings
- Super
- Nicholas Zakas: https://github.com/nzakas/understandinges6
- Dr. Axel Rauschmayer: http://www.2ality.com/2014/08/es6-today.html
- Luke Hoban: https://github.com/lukehoban/es6features
Object.assign
is also awesome. (essentially_.extend
)