Skip to content


Created: 2015-08-25 18:06:19 -0700 Modified: 2021-05-15 11:22:10 -0700

Read this:

These sites are both great resources:

I’m only going to be making notes here that I think are useful for the future.


Function with default object parameters

Section titled Function with default object parameters

This syntax gives defaults to not only the operands, but it also gives a default to the object passed in altogether, so you can call it with zero arguments if you want.

function sum({operand1 = 5, operand2 = 6} = {}) {
return operand1 + operand2;

Yes, “let” is block-scoped, and will probably become the default scoping for almost everything, because function-scoping (and hoisting) with “var” isn’t usually what you want. However, there’s a nice little gem thanks to having block-scoping:

ES5 (this sucked):

var result = [];
for (var i = 0; i < 5; i++) {
result.push(function () {
return i;
result[0]() === 5;
result[1]() === 5;


var result = [];
for(var i = 0; i < 5; i++) {
**let val = i;**
result.push(function() {
return val;
console.log('Result[0]: ' + result[0]()); // 0
console.log('Result[1]: ' + result[1]()); // 1
// Slightly cleaner syntax:
let result = [];
for(let i = 0; i < 5; i++) {
result.push(function() {
return i;
console.log('Result[0]: ' + result[0]()); // 0
console.log('Result[1]: ' + result[1]()); // 1


Shorthand for anonymous functions in JavaScript. Useful for callbacks to turn this:

$("#hi").click(function (event) {

Into this:

$("#hi").click((event) => console.log("clicked"));

You can define a whole function with this too:

var addOneAndLog = (x) => {
console.log("x is: " + x);
return x;
var y = addOneAndLog(5); // prints 6
console.log("y is: " + y); // prints 6

To define a function with no arguments, do:

var myFunction = () => {
/_ … body … _/;


  • It still captures any other variables in closures.
  • ‘this’ is always the ‘this’ from the scope that defines the function, meaning call, apply, and bind have NO effect.


  • Because ‘this’ can’t be modified, I would only ever use this as a lambda or as a quick callback function. You would never use this to write class functions.


A way to destructure objects and arrays:

let test = {name: ‘Adam’, x: 2};

let {name: myName, x: numHands} = test;

console.log(‘My name is: ’ + myName + ’ and I have ’ + numHands + ’ hands.’); // My name is Adam and I have 2 hands.

This is handy for something like this:

function getResult() {

return {

result: 1234,

error: null



var {result, error} = getResult();

console.log(result); // 1234

I’ve also seen it used in code like this:

ES5: var black =;

ES6: const { black } = this.props; // it’s fewer characters and it’s const

You can also do this for arrays:

var [first, last] = [‘Adam’, ‘Learns’];

console.log(first, last); // “Adam” “Learns”

That may be useful if you got data in an array that you know is something it’s in a certain structure, but to me that means you should’ve used an object where you could explicitly name your properties.

However, there is a “car”/“cdr” style too:

let [first, … remaining] = [1,2,3,4,5]; // the ”…” is the “spread” operator

console.log(first); // 1

console.log(remaining); // [2,3,4,5]

You can also implicitly reject elements in an array without having to use something like an “_ignore” variable:

let [,,third] = [1,2,3]; // 3

Similarly, the “spread” operator can be used for calling a function:

var extraParams = [3,4,5];

function foo(a, b, c, d, e) {



foo(1,2, … extraParams); // 15 (and note: the spread operator may be copy/pasted out of OneNote as a single-character ellipsis, but it is supposed to be three periods)

The spread operator can also do something like this:

var a = {

foo: 5,

bar: 6


var b = {

…a, // shallow-copies all properties of ‘a’ into this, meaning will now modify too.

baz: 7


console.log(‘b: ’ + JSON.stringify(b)); // b: {“foo”:5,“bar”:6,“baz”:7}


Try to use underscore variables at LEAST in your getters/setters.

Invalid code (well, not invalid, but you’ll infinitely recurse, meaning it won’t work):

class Person {

constructor(first, last) {

this.first = first;

this.last = last;


get first() { return this.first; }

set first(f) { this.first = f; } // NOT GOOD: this function calls itself infinitely

toString() {

return ${this.first} ${this.last};



Change it to:

class Person {

constructor(first, last) {

this.first = first;

this.last = last;


get first() { return this._first; } // I only had to change the getter/setter to use “_first” instead of “first”.

set first(f) { this._first = f; } // the rest of the code works fine because these functions don’t need parens to be invoked.

toString() {

return ${this.first} ${this.last};



Remember: don’t use getters/setters instead of explicit function calls when you want side effects. For example, having a getter for something like “get lengthInInches() { return this.lengthInFeet * 12; }” is fine because you’re not modifying the state of the class. But saying “get nextId() { return; }” is bad because it’s not obvious that there are even side effects, e.g.:

if (this.nextId > 0 && this.nextId < 10) {

console.log(‘Congrats! You are one of our first users.’);


if (this.nextId === 0) {

console.log(‘This will never be hit now!’);


The problem is that you’re incrementing nextId just by accessing it, but it’s not obvious to a user of the API that there would even be side effects.


In ES5, you basically had to pollute the global namespace for client-side imports. For example, in the Google Closure Library, you had something like this:

// constants.js

goog.provide(‘’); = PI = 3.141592653589793;

// main.js


console.log(; // 3.141592653589793

The problem with this is that you really had a global namespace in the form of “” (well, it wasn’t necessarily rooted at ‘window’, but you get the idea). This meant that “my” was now a global variable.

With ES6, you don’t need to come up with a namespace at all since you import based on relative paths.

import * as constants from “src/constants.js”

constants.PI; // 3.141592653589793

What’s nice is that “constants.js” isn’t the one coming up with the name for the namespace; the user of the file is. This means constants.js can now look like this:

// constants.js

export var PI = 3.141592653589793; // now we don’t care if some other module defined their own PI


This was actually in ES5, but I didn’t know about it:

x = 5;

y = ‘hi’;

console.log(x); // 5

console.log(y); // hi

console.log({x}); // Object {x: 5}

console.log({y}); // Object {y: ‘hi’}

console.log({x, y}); // Object {x: 5, y: ‘hi’}

So console.log({someObj}) is essentially shorthand for console.log(‘someObj: ’ + someObj);

It doesn’t beat the “stringify” snippet I wrote in Sublime to do console.log(‘objectToLogHere: ’ + JSON.stringify(objectToLogHere));

Thanks to default parameters, you shouldn’t ever see something like this anymore:

function Person(name) { = name || ‘Adam’; // BAD: see below for why


Instead, change the signature of the function:

function Person(name=‘Adam’) { = name; // much nicer!


This is great because sometimes defaults didn’t work how you might expect. E.g. if you had a default number that was non-zero:

function Person(numArms) {

this.numArms = numArms || 2; // BAD: if you lost both of your arms and passed in 0, “0 || 2” evaluates to 2, so you’re still given two arms.


// Fix it like this:

function Person(numArms = 2) {

this.numArms = numArms;


And yes, I actually did run into this in practice. I had something along the lines of “this.resourceMultiplier = multiplier || 1”, so I couldn’t ever set it to 0 thanks to that line.


Note: I am doing this on 8/26/2015, so ES5 is still common enough for me to have to use a transpiler.

mkdir learning_es6

cd learning_es6


npm install

npm install —save-dev gulp

npm install —save-dev gulp-babel

npm install —save-dev babel

Make a basic gulpfile.js in the root directory:

var gulp = require(‘gulp’);

var babel = require(‘gulp-babel’);

var paths = {

jsCode: [‘./src/**/*.js’],

dist: ‘dist’


gulp.task(‘default’, function () {

return gulp.src(paths.jsCode, {base: ’./’})




Expose “dist” to your views in Express:

app.use(‘/dist’, express.static(path.join(__dirname, ‘dist’)));

Note that I explicitly expose it here as “dist”. If you leave off the first argument, then you can also leave off “dist” from the path below.

Set up your index.jade:

doctype html



title Learning ES6

script(type=‘text/javascript’, src=‘dist/src/main.js’)

body(onload=‘main.start()’ style=“overflow: hidden;“)

Set up a main.js (as shown above, I put this in a folder called “src”, but you may want it in publicjavascripts):

class Person {

constructor(name) { = name;

console.log(‘ ’ + JSON.stringify(;



window.main = {};

main.start = function() {

let person = new Person(‘Adam’);


Run “gulp” so that your file is transpiled and placed into the “dist” folder:


Finally, launch your HTTP server with this on Windows:

set DEBUG=learning_es6:* & node .binwww

Go to http://localhost:3000

Now you’re up and running with ES6/Babel.