본문 바로가기
What I Learned/Javascript

Learning ECMScript 6+ (ES6+)

by 단풍국범생이 2021. 2. 25.

2. Variables and Data Structures

1) let keyword

- let is helping us enforce block scoping in JavaScript.

// Example 1(1) - var
var topic = "JavaScript";
if (topic) {
	var topic = "ECMAScript";
    console.log("block", topic);
}
console.log("global", topic); // expected "global ECMAScript"

// Example 1(2) - let
var topic = "JavaScript";
if (topic) {
	let topic = "ECMAScript";
    console.log("block", topic);
}
console.log("global", topic); // expected "global JavaScript"


// Example 2
<!DOCTYPE html>
<html>
  <head>
    <title>ECMAScript</title>
    <style>
      #box {
        display: flex;
        justify-content: space-around;
      }
      #box > div {
        height: 5em;
        width: 5em;
        background-color: purple;
      }
    </style>
  </head>
  <body>
    <h1>Let</h1>
    <div id="box"></div>
    <script type="text/javascript">
      var div;
      var box = document.getElementById("box");

      for (let i = 0; i < 5; i++) {
        div = document.createElement("div");
        div.onclick = function () {
          alert("This is box # " + i);
        };
        box.appendChild(div);
      }
    </script>
  </body>   
</html>
for (var i = 0; i < 5; i++) {
	div = document.createElement("div");
	div.onclick = function () {
		alert("This is box # " + i);
	};
	box.appendChild(div);
}

- In this case, the alert will only print "This is box # 5" because var is not scoped protected. The value of i is kept changing when looping.

2) const keyword

<!DOCTYPE html>
<html>
  <head>
    <title>ECMAScript</title>
  </head>
  <body>
    <h1>Const</h1>
    <script type="text/javascript">
      const pizza = true;
      pizza = false;
      console.log(pizza);
    </script>
  </body>
</html>

3) template strings

function print(firstName) {
  console.log(`Hello ${firstName}`);
}

print("Jenny");

function createEmail(firstName, price) {
  let shipping = 5.95;
  console.log(`Hi ${firstName}! Thanks!
      Total: $${price}
      Shipping: $${shipping}
      Grand Total: $${price + shipping}
    `);
}

createEmail("Guy", 100);

4) Searching strings

- startsWith, endsWith, includes, and search functions

- search function tells me where (position) the string shows up.

const planet = "Earth";
console.log(planet.startsWith("E")); // case sensitive
console.log(planet.endsWith("h"));
console.log(planet.includes("h"));
console.log(planet.search("h")); // expected 1

5) Symbols

- You can give a unique identifier. If you want to capture a unique identifier and associate that with an object, you can use the symbol.

- If you set an object with a key named id, there is no naming conflict.

const id = Symbol();

const courseInfo = {
  title: "JavaScript",
  topics: ["strings", "arrays", "objects"],
  id: "js-course"
};

courseInfo[id] = 41284;
console.log(courseInfo);

6) Maps

- In a map, any value, both objects, and primitive values may be used either as a key or a value.

- map is different than an object, so you can't just access the keys with dot notation.

let course = new Map();

course.set("react", { description: "ui" });
course.set("jest", { description: "testing" });

// console.log(course);
// console.log(course.react); // expected undefined
// console.log(course.get("react"));

let details = new Map([
  [new Date(), "today"],
  [2, { javascript: ["js", "node", "react"] }],
  ["items", [1, 2]]
]);

// console.log(details.size);

details.forEach(function (item) {
  console.log(item);
});

7) Sets

- Each value must be unique.

let books = new Set();
books.add("Pride and Prejudice");
books.add("War and Peace").add("Oliver Twist");
books.add("Pride and Prejudice"); // expected not included in the set.

console.log(books);
console.log(books.size);

books.delete("Oliver Twist");

console.log(
  "has Oliver Twist",
  books.has("Oliver Twist")
);
let books = new Set();

books.map(function (item) {
	console.log(item);
});

- This triggers an error that says "book.map is not a function."

 


3. Arrays and Array Methods

1) Spread Operator

- It is used to spread the data in an array from multiple arrays.

let cats = ["Biscuit", "Jungle"];
let dogs = ["Stella", "Camper"];

let animals = [
  "Smoky",
  "Miro",
  "Swimmy",
  ...cats,
  ...dogs
];

 

2) Destructuring Arrays

- It can be used to assign a variable name to a position in an array

// Not using destructuring
let cities = [
  "Spokane",
  "Boston",
  "Los Angeles",
  "Seattle",
  "Portland"
];
console.log(cities[0]);

// Using desctructuring
let [first, , , , fifth] = [
  "Spokane",
  "Boston",
  "Los Angeles",
  "Seattle",
  "Portland"
];

console.log(first);
console.log(fifth);

 

3) .includes function

- Before, you had to use third-party libraries to do this function.

let cities = [
  "Spokane",
  "Boston",
  "Los Angeles",
  "Seattle",
  "Portland"
];

console.log(cities.includes("Boston"));
console.log(cities.includes("Santa Barbara"));

 


4. ECMAScript Objects

1) Object Literal Enhancement

// No object literal enhancement
function skier(name, sound) {
  return {
    name: name,
    sound: name,
    powderYell: function () {
      let yell = this.sound.toUpperCase();
      console.log(`${yell}! ${yell}!`);
    }
  };
}

// Object literal enhancement
function skier(name, sound) {
  return {
    name,
    sound,
    powderYell: function () {
      let yell = this.sound.toUpperCase();
      console.log(`${yell}! ${yell}!`);
    }
  };
}

skier("Sendy", "yeah").powderYell();

2) Spread Operator for objects

const daytime = {
  breakfast: "oatmeal",
  lunch: "peanut butter and jelly"
};

const nighttime = "mac and cheese";

const backpackingMeals = {
  ...daytime,
  nighttime
};

console.log(backpackingMeals);

3) Destructuring objects

- Difference between arrays is objects always use curly braces.

- Example 1: put vacation in the argument and the marketing function is using only the destination and activity of the vacation object.

// Example 1
const vacation = {
  destination: "Chile",
  travelers: 2,
  activity: "skiing",
  cost: "so much"
};

function marketing({ destination, activity }) {
  return `Come to ${destination} and do some ${activity}`;
}

console.log(marketing(vacation));

// Example 2
const { title, price } = {
  title: "Reuben",
  price: 7,
  description: "A classic",
  ingredients: [
    "bread",
    "corned beef",
    "dressing",
    "sauerkraut",
    "cheese"
  ]
};

console.log(title);
console.log(price);

4) for/of Loop

for (let letter of "JavaScript") {
  console.log(letter);
}

let topics = new Map();
topics.set("HTML", "/topic/html");
topics.set("CSS", "/topic/css");
topics.set("JavaScript", "/topic/javascript");

for (let topic of topics.entries()) {
  console.log(topic);
}

5) classes

class Vehicle {
  constructor(description, wheels) {
    this.description = description;
    this.wheels = wheels;
  }
  describeYourself() {
    console.log(
      `I am a ${this.description} 
        with ${this.wheels} wheels.`
    );
  }
}

let coolSkiVan = new Vehicle("cool ski van", 4);

console.log(coolSkiVan);
coolSkiVan.describeYourself();

6) Inheritance

class Vehicle {
  constructor(description, wheels) {
    this.description = description;
    this.wheels = wheels;
  }
  describeYourself() {
    console.log(
      `I am a ${this.description} 
      with ${this.wheels} wheels.`
    );
  }
}
class SemiTruck extends Vehicle {
  constructor() {
    super("semi truck", 18);
  }
}
// groceryStoreSemi object can use describeYourself function because it extends Vehicle object.
let groceryStoreSemi = new SemiTruck();
groceryStoreSemi.describeYourself();

7) Getter and Setter

// Example 1
let attendance = {
	_list: [],
    set addName(name){
    	this._list.push(name);
    },
    get list(){
    	return this._list.join(", ");
    }
};
attendance.addName = "Joanne Starr";
attendance.addName = "Charlie Charlson";

// Example 2
class Hike {
  constructor(distance, pace) {
    this.distance = distance;
    this.pace = pace;
  }
  get lengthInHours() {
    return `${this.calcLength()} hours`;
  }
  calcLength() {
    return this.distance / this.pace;
  }
}

const mtTallac = new Hike(10, 2);

console.log(mtTallac.lengthInHours);

- Setter and Getter look like a function but it is not considered as a function in JavaScript. If you try to call them with braces, it will give you an error.

 


5. ECMAScript Functions

1) string.repeat Function

let yell = "woo!";

let party = yell.repeat(20);

console.log(party);

let cat = {
  meow(times) {
    console.log("meow".repeat(times));
  },
  purr(times) {
    console.log("prrr".repeat(times));
  },
  snore(times) {
    console.log("ZzZzZ".repeat(times));
  }
};

cat.meow(3);
cat.purr(3);
cat.snore(6);

2) Default function parameters

- If you don't put a parameter, it uses the default parameters.

function add(x = 5, y = 6) {
  console.log(x + y);
}

add(1, 2);

function haveFun(
  activityName = "hiking",
  time = 3
) {
  console.log(`Today I will go ${activityName}
    for ${time} hours.`);
}

haveFun("biking", 2.5);
haveFun("biking");

3) Arrow Function

- If there is only one statement inside the function, you can erase curly braces.

// =>

// Example 1
// No arrow function
let studentList = function(students) {
	console.log(students);
}

// Arrow function
let studentList = (students) =>
  console.log(students);

studentList(["A", "B", "C"]);

// Example 2
let list = ["apple", "banana", "strawberry"];

// No arrow function
list.map(function(item){
	console.log(item);
})

// Arrow function
list.map((item) => console.log(item));

4) this in Arrow Function

// this with no arrow (1)
let person = {
  first: "Angie",
  hobbies: ["bike", "hike", "ski"],
  printHobbies: function () {
    this.hobbies.forEach(function(hobby) {
      let string = `${this.first} likes to ${hobby}`;
      console.log(string);
    });
  }
};

person.printHobbies();

- It does not recognize what this is if you use the function without an arrow.

// this with no arrow (2)
let person = {
  first: "Angie",
  hobbies: ["bike", "hike", "ski"],
  printHobbies: function () {
	let _this = this;
    this.hobbies.forEach(function(hobby) {
      let string = `${_this.first} likes to ${hobby}`;
      console.log(string);
    });
  }
};

// this with arrow
let person = {
  first: "Angie",
  hobbies: ["bike", "hike", "ski"],
  printHobbies: function () {
    this.hobbies.forEach((hobby) => {
      let string = `${this.first} likes to ${hobby}`;
      console.log(string);
    });
  }
};

person.printHobbies();

- A little workaround that you often see in JavaScript code is using other variables to scope "this" to the function.

- Using an arrow is the better approach. The arrow is helping us keep "this" in scope.

5) Generators

- You know you are looking at a generator when you see an asterisk.

- It allows us to pause functions in the middle of execution to be resumed later.

- The yield keyword is going to be used anytime we want to hit pause inside the execution of a function.

- In order to skip to the next yield, we just call the next function.

function* director() {
  yield "Three";
  yield "Two";
  yield "One";
  yield "Action";
}

let countdown = director();

console.log(countdown.next().value);
console.log(countdown.next().value);
console.log(countdown.next().value);
console.log(countdown.next());
console.log(countdown.next());

 


6. Asynchronous JavaScript

1) Promises

- When something is asynchronous, it just means that some sort of waiting is going on. There's a delay between when we ask for something and when we receive it.

- resolve means if everything goes well as expected with the promise, it will resolve, it's the function that's going to be called.

- Anything we are passing into the .then function is "resolve".

const delay = (seconds) =>
  new Promise((resolve, reject) => {
    if (typeof seconds !== "number") {
      reject(
        new Error("seconds must be a number")
      );
    }

    setTimeout(resolve, seconds * 1000);
  });

console.log("Zero seconds");
delay("one").then(() => console.log("1 sec"));

 

2) Loading remote data with promises

const spacePeople = () => {
  return new Promise((resolves, rejects) => {
    const api =
      "http://api.open-notify.org/astros.json";
    const request = new XMLHttpRequest();
    request.open("GET", api);
    request.onload = () => {
      if (request.status === 200) {
        resolves(JSON.parse(request.response));
      } else {
        rejects(Error(request.statusText));
      }
    };
    request.onerror = (err) => rejects(err);
    request.send();
  });
};

spacePeople().then(
  (spaceData) => console.log(spaceData),
  (err) =>
    console.error(new Error("Can't load people"))
);

 

3) Returning promises with fetch (This is to make #2 in a better way)

- The fetch function is built into every single browser, so you can use this instead of writing those long XML, HTTP requests.

- The fetch returns a promise. It is just a cleaner wrapper around them.

let getSpacePeople = () =>
  fetch(
    "http://api.open-notify.org/astros.json"
  ).then((res) => res.json());

let spaceNames = () =>
  getSpacePeople()
    .then((json) => json.people)
    .then((people) => people.map((p) => p.name))
    .then((names) => names.join(", "));

spaceNames().then(console.log);
// spaceNames().then((data) => console.log(data)); 
// is also allowed but I don't want to repeat the same word 'data'.

 

4) async/await syntax

- Async functions return a promise and resolve the value of the promise.

- Await is only valid in the async function.

const delay = (seconds) =>
  new Promise((resolves) =>
    setTimeout(resolves, seconds * 1000)
  );

const countToFive = async () => {
  console.log("zero seconds");
  await delay(1);
  console.log("one second");
  await delay(2);
  console.log("two seconds");
  await delay(3);
  console.log("three seconds");
};

countToFive();

 

5) Incorporating fetch with async/await

- It usually is used to fetch data from external APIs.

- We wait for all sorts of things to occur.

- First, we're waiting for a fetch from an API. Then we're going to convert that response to JSON. Once we have it, we can log it into the console.

const githubRequest = async (login) => {
  let response = await fetch(
    `https://api.github.com/users/${login}`
  );
  let json = await response.json();
  let summary = `${json.name}, ${json.company}`;
  console.log(summary);
};

githubRequest("eveporcello");

 

All the sources and codes are from a lecture on LinkedIn Learning called "Learning ECMAScript 6+ (ES6+)" lectured by Eve Porcello.