What You'll Learn

JavaScript is what everyone calls the language, but the official name of JavaScript is ECMAScript. That name comes from the standards organization Ecma, which manages the language standard. ECMAScript 1 (June 1997) was the first version of the JavaScript language standard.

Up until now, you've mostly been writing ECMAScript 5. ES5 is comfortable and familiar, but ES6 gives us a lot of great new features, which we'll start learning about this week.

Recap

We"ve learned that scope is the area of code in which a variable or value can be accessed.

We already know that variables declared (using the keyword var) inside of a function will remain scoped to that function and hoisted to the top of that function scope. In other words, it won"t be accessible outside of the function.

In short we have 2 scopes, global and function scope.

What is the differences?

ES6 gives us two new variable keywords: let and const. These two variable keywords introduce block scope. This means the variable will be confined to the scope of a block that it is defined in, such as an if statement or for loop and will not be accessible outside of the opening and closing curly braces of the block.

function blockScoping() {
  if (true) {
    // this will throw an error
    const x = 24;
    let y = 10;
    // this works
    // var x = 24;
    // var y = 10;
  }
  return { x: x, y: y };
}
function temporalDeadZone() {
  console.log(myVar);
  console.log(myLet);
  console.log(myConst);
  var myVar = "var";
  // you can use variables before they"re defined with let and const
  let myLet = "let";
  const myConst = "const";
  return { myVars, myLets, myConsts };
}
const obj = { a: 1, b: 2 };
obj.b = 3;
// obj: {a: 1, b: 3}

Object shorthand is a way of declaring an object's properties and those properties values quickly and easily.

Intuitive and flexible destructuring of Objects into in dividual variables during assignment.

function shorthandPropertyNames() {
  const red = Math.floor(Math.random() * 256);
  const green = Math.floor(Math.random() * 256);
  const blue = Math.floor(Math.random() * 256);
  return { red, green, blue };
  // instead of
  return {
    red: red,
    green: green,
    blue: blue,
  };
}

console.log(shorthandPropertyNames());

Summary: We can assign a property's name and it's value to an object using a variable. The variable name becomes the property and the variables data will become the property value.

const name = "Parrot";
const colors = ["Red", "Green", "Blue", "Yellow"];

const bird = {
  name: name,
  colors: colors,
};

console.log(bird);
const name = 'Parrot'
const colors = ['Red', 'Green', 'Blue', 'Yellow']
const talons = // CHANGE ME

const bird = {
  name: name,
  colors: colors,
  // CHANGE ME
}

console.log(bird)
const capital = "Hanoi";
const continent = "Asia";

const vietnam = {
  // CHANGE ME
};

console.log(vietnam);
const wheelsCount = 4;
const doorsCount = 4;
const color = "black";

const car = {
  // CHANGE ME
};

console.log(car);

Destructuring is a way of grabbing properties off of an object and sticking them inside variables.

// Object destructuring
const obj = { first: "Jane", last: "Doe" };
const { first, last } = obj; // first = "Jane"; last = "Doe"
const { first: f, last: l } = obj; // f = "Jane"; l = "Doe"

const state = { counter: 1, list: ["a", "b"] };
// no object destructuring
const list = state.list;
const counter = state.counter;
// object destructuring
const { list, counter } = state;
// Array destructuring
const iterable = ["a", "b"];
const [x, y] = iterable; // x = "a"; y = "b"

Pick what you need

If you destructure an object, you mention only those properties that you are interested in:

const { x: x } = { x: 7, y: 3 }; // x = 7

If you destructure an Array, you can choose to only extract a prefix:

const [x, y] = ["a", "b", "c"]; // x="a"; y="b";

Another great feature is the rest destructuring. It is often used for splitting out a part of an object, but keeping the remaining properties in another object. MDN: Rest parameters

const state = { counter: 1, list: ["a", "b"] };

// rest destructuring
const { list, ...rest } = state;

console.log(rest);
// output: { counter: 1 }
console.log(list);
// output: ["a", "b"]

The spread operator comes with three ..., but shouldn"t be mistaken for the rest operator. It depends on the context where it is used. Used within a destructuring (see above), it is as rest operator. Used somewhere else it is a spread operator. MDN: Spread syntax

let arr = [-1, 5, 11, 3];
console.log(Math.max(...arr));

Another example to append an array to another array:

const arr1 = ["a", "b"];
const arr2 = ["c", "d"];

arr1.push(...arr2);
// arr1 is now ["a", "b", "c", "d"]

Or to concatenate Arrays:

const x = ["a", "b"];
const y = ["c"];
const z = ["d", "e"];

const arr = [...x, ...y, ...z]; // ["a", "b", "c", "d", "e"]

Many functions will take objects as their arguments. When our functions accept an argument as their parameter, then we'll often want to extract the objects properties. We can do so more easily by using:

function getAverage(obj) {
  return Math.floor((x + y + z) / 3.0); // CHANGE ME
}

getAverage({ x: 3.6, y: 7.8, z: 4.3 });
function getAddress(obj) {
  return city === "HCMC" && country === "Vietnam" && street === "Ton Dan"; // CHANGE ME
}

getAddress({
  city: "HCMC",
  country: "Vietnam",
  address: {
    number: 12,
    street: "Ton Dan",
    district: "4",
  },
});
function objectifyElements(arr) {
  return { first, second, third }; // CHANGE ME
}

objectifyElements([0, 1, 2, 3, 4, 5, 6, 7, 8]).fourth === 4;
function getFoodItems() {
  const food = [
    ["carrots", "beans", "peas", "lettuce"],
    ["apples", "mangos", "oranges"],
    ["cookies", "cake", "pizza", "chocolate"],
  ];
  const carrots = food[0][0];
  const cookies = food[2][0];
  const mangos = food[1][2]; // CHANGE ME

  return { carrots, cookies }; // CHANGE ME
}

getFoodItems().mangos === "mangos";
function getHistoricPrices(index) {
  const bingo = index; // CHANGE ME
  return bingo;
}

getHistoricPrices([true, false, true]);
function getHistoricPrices(index) {
  const bingo = index; // CHANGE ME
  return bingo;
}

getHistoricPrices([
  [true, false],
  [false, true],
]);
function getHistoricPrices(index) {
  const bingo = index; // CHANGE ME
  return bingo;
}

getHistoricPrices([
  [
    [true, false],
    [true, false],
  ],
]);
function getHistoricPrices(index) {
  const bingo = index; // CHANGE ME
  return bingo;
}

getHistoricPrices([[[{}, {}]]]);

Rest parameters allow us to collect an unknown number of arguments passed to a function into an array.

ES6 gives us more ways to handle parameters.

Default parameters:

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

f(1); // 50

Rest parameter:

function f(x, y, ...a) {
  return (x + y) * a.length;
}
f(1, 2, "hello", true, 7); // 9
function restParams(first, ...rest) {
  return first === "first" && rest[0] === "second";
}

console.log(restParams(1)); // CHANGE ME
function restParams2(first, ...rest) {
  return first === "first" && rest[0] === "second" && rest[1] === "third";
}

console.log(restParams2(1)); // CHANGE ME
function restParams3(first, ...rest) {
  return (
    first === "first" &&
    rest[0] === "second" &&
    rest[1] === "third" &&
    rest[2] === undefined
  );
}

console.log(restParams3()); // CHANGE ME
function restParams4(...rest) {
  return rest[2] === "first" && rest[0] === "second" && rest[1] === "third"; // CHANGE ME
}

console.log(restParams4("first", "second", "third"));
function restParams5(...rest) {
  return rest; // CHANGE ME
}

restParams5(1, 2, 3, 4, 5, 6) === 6;
function findTheMax() {
  const arr1 = [1, 7, 2, 4];
  const arr2 = [1, 9, 5, 8];
  return [arr1];
}
function concatenateArrays() {
  const arr1 = [0, 1, 2, 3];
  const arr2 = [4, 5, 6];
  const arr3 = [7, 8, 9];
  const result = // CHANGE ME
  return result;
}
function mergeObjects() {
  // what does this return?
  const obj1 = {
    a: "a from obj1",
    b: "b from obj1",
    c: "c from obj1",
    d: {
      e: "e from obj1",
      f: "f from obj1",
    },
  };
  const obj2 = {
    b: "b from obj2",
    c: "c from obj2",
    d: {
      g: "g from obj2",
      h: "h from obj2",
    },
  };
  const result = { ...obj1, ...obj2 };
  return (
    result.a === "YOUR_ANSWER" &&
    result.b === "YOUR_ANSWER" &&
    result.c === "YOUR_ANSWER" &&
    result.d.e === "YOUR_ANSWER" &&
    result.d.f === "YOUR_ANSWER" &&
    result.d.g === "YOUR_ANSWER" &&
    result.d.h === "YOUR_ANSWER"
  );
}

ES6 introduced arrow functions, which allow us to write functions with shorter syntax.

To name an arrow function, you must save it as a variable. If the function has only one statement, and the statement returns a value, you can remove the brackets and the return keyword:

function getFive() {
  return 5;
}
// Arrow function that has no parameter and returns value by default
const getFive = () => 5;

function divide(a, b) {
  return a / b;
}
// Arrow function with parameters
const divide = (a, b) => a / b;

Multiple lines or expressions in an arrow function require the curly braces {} and the keyword return

const squared = (x) => {
  console.log(x);
  return x * x;
}; // block
const squared = (x) => x * x; // expression

Summary

Arrow functions are handy for one-liners. They come in two flavors:

  1. Without curly braces: (...args) => expression - the right side is an expression: the function evaluates it and returns the result.
  2. With curly braces: (...args) => { body } - brackets allow us to write multiple statements inside the function, but we need an explicit return to return something.

x

function multiArgument() {
  // CHANGE BELOW
  const divide = function (a, b) {
    return a / b;
  };
  return divide(40, 10);
}
function spreadWithArrow() {
  // CHANGE BELOW
  const asArray = function (...args) {
    return args;
  };
  return asArray(1, 2, 3, 4);
}
function withObject() {
  // CHANGE BELOW
  const getObject = function (favoriteCandy) {
    return { favoriteCandy };
  };
  return getObject("twix");
}
function withMultiLineExpression() {
  // CHANGE BELOW
  const getString = function (name) {
    return `
        Hello there ${name}
        How are you doing today?
      `;
  };
  return getString("Ryan");
}
function curryAdd() {
  // CHANGE BELOW
  return curryAddition(9)(3)(5);
  function curryAddition(a) {
    return function (b) {
      return function (c) {
        return a + b + c;
      };
    };
  }
}

Rest parameters allow us to collect an unknown number of arguments passed to a function into an array.

Additional reading

Solutions

Code