學習筆記之ES6的查缺補漏(英)

Three reasons for the ES5 to ES6 updates are listed below:

  • A similarity to other programming languages — JavaScript ES6 is syntactically more similar to other object-oriented programming languages. This leads to less friction when experienced, non-JavaScript developers want to learn JavaScript.
  • Readability and economy of code — The new syntax is often easier to understand (more readable) and requires fewer characters to create the same functionality (economy of code).
  • Addresses sources of ES5 bugs — Some ES5 syntax led to common bugs. With ES6, Ecma introduced syntax that mitigates some of the most common pitfalls.

 

1. const

a const variable cannot be reassigned because it is constant. If you try to reassign a const variable, you'll get a TypeError.

Constant variables must be assigned a value when declared.


 

2. String Interpolation

In the ES6 version of JavaScript, we can insert, or interpolate, variables into strings using template literals.

var myPet = 'armadillo';
console.log(`I own a pet ${myPet}.`);

 

3. Truthy and Falsy Assignment

Because || or statements check the left-hand condition first, the variable defaultName will be assigned the actual value of username if is truthy, and it will be assigned the value of 'Stranger' if username is falsy.

let defaultName = username || 'Stranger';


 

4. Arrow Functions

ES6 introduced arrow function syntax, a shorter way to write functions by using the special "fat arrow" () => notation.

const rectangleArea = (width, height) => {
  let area = width * height;
  return area;
}

 

5. Concise Body Arrow Functions

Functions that take only a single parameter do not need that parameter to be enclosed in parentheses. However, if a function takes zero or multiple parameters, parentheses are required.

A function body composed of a single-line block does not need curly braces. Without the curly braces, whatever that line evaluates will be automatically returned. The contents of the block should immediately follow the arrow => and the return keyword can be removed. This is referred to as implicit return.


 

6. Methods

When the data stored on an object is a function we call that a method. A property is what an object has, while a method is what an object does.

With the new method syntax introduced in ES6 we can omit the colon and the function keyword.

const alienShip = {
  invade () { 
    console.log('Hello! We have come to dominate your planet. Instead of Earth, it shall be called New Xaculon.')
  }
};

 

7. Arrow Functions and this

const goat = {
  dietType: 'herbivore',
  diet: () => {
    console.log(this.dietType);
  }
};
goat.diet(); // Prints undefined

Arrow functions inherently bind, or tie, an already defined this value to the function itself that is NOT the calling object. In the code snippet above, the value of this is the global object, or an object that exists in the global scope, which doesn't have a dietType property and therefore returns undefined.

solution: write the function using either longhand or shorthand format.


 

8. Setters&Getters

const robot = {
  _model: '1E78V2',
  _energyLevel: 100,
  _numOfSensors: 15,
  set numOfSensors(num) {
    if (typeof num === 'number' && num >= 0){
      this._numOfSensors = num;
    }else {
      console.log('Pass in a number that is greater than or equal to 0');
    }
  },
  get numOfSensors(){
    if(typeof this._numOfSensors === 'number'){
      return this._numOfSensors;
    } else {
      return 'Sensors are currently down.'
    }
  },
};
robot.numOfSensors = 100;
console.log(robot.numOfSensors);

 

9. Factory Functions

function robotFactory(model, mobile){
  return {
    model: model,
    mobile: mobile,
    beep() {
      console.log('Beep Boop');
    }
  }
}

use a destructuring technique, called property value shorthand, to save ourselves some keystrokes:

function robotFactory(model, mobile){
  return {
    model,
    mobile,
    beep() {
      console.log('Beep Boop');
    }
  }
}

 

10. Destructured Assignment

a destructuring technique called destructured assignment to save ourselves some keystrokes

Take for example the following object:

const vampire = {
  name: 'Dracula',
  residence: 'Transylvania',
  preferences: {
    day: 'stay inside',
    night: 'satisfy appetite'
  }
};

 

we create a variable with the name of an object's key that is wrapped in curly braces { } and assign to it the object. Take a look at the example below:

const { residence } = vampire; console.log(residence); // Prints 'Transylvania'

 

We can even use destructured assignment to grab nested properties of an object:

const { day } = vampire.preferences; console.log(day); // Prints 'stay inside'

 

11. class - subclass

class Cat extends Animal {
  constructor(name, usesLitter) {
    super(name);
    this._usesLitter = usesLitter;
  }
}

 

12. Browser Compatibility and Transpilation

 two important tools for addressing browser compatibility issues: caniuse.com & Babel


 

13. export & import Module

import

import Menu from './menu';
import { specialty, isVegetarian } from './menu';
import * as Carte from './menu';

exports

export { specialty, isVegetarian };
export { specialty as chefsSpecial, isVegetarian as isVeg, isLowSodium };
export default Menu;

 

14. Promise

Promises are objects that represent the eventual outcome of an asynchronous operation. A Promise object can be in one of three states:

  • Pending: The initial state— the operation has not completed yet.
  • Fulfilled: The operation has completed successfully and the promise now has a resolved value. For example, a request’s promise might resolve with a JSON object as its value.
  • Rejected: The operation has failed and the promise has a reason for the failure. This reason is usually an Error of some kind.

The executor function has two function parameters, usually referred to as the resolve() and reject() functions. The resolve() and reject() functions aren’t defined by the programmer. When the Promise constructor runs, JavaScript will pass its own resolve()and reject() functions into the executor function.

  • resolve is a function with one argument. Under the hood, if invoked, resolve() will change the promise’s status from pending to fulfilled, and the promise’s resolved value will be set to the argument passed into resolve().
  • reject is a function that takes a reason or error as an argument. Under the hood, if invoked, reject()will change the promise’s status from pending to rejected, and the promise’s rejection reason will be set to the argument passed into reject().

(1) example executor function in a Promise constructor:

const executorFunction = (resolve, reject) => {
  if (someCondition) {
      resolve('I resolved!');
  } else {
      reject('I rejected!'); 
  }
}const myFirstPromise = new Promise(executorFunction);

(2) Chaining Multiple Promises

checkInventory(order)
.then((resolvedValueArray) => {
  // Write the correct return statement here:
 return processPayment(resolvedValueArray);
})
.then((resolvedValueArray) => {
  // Write the correct return statement here:
  return shipOrder(resolvedValueArray);
})
.then((successMessage) => {
  console.log(successMessage);
})
.catch((errorMessage) => {
  console.log(errorMessage);
});

We should chain multiple promises rather than nesting them.

To use promise composition correctly, we have to remember to return promises constructed within a .then().

(3) Promise.all()

To maximize efficiency we should use concurrency, multiple asynchronous operations happening together. With promises, we can do this with the function Promise.all().

Promise.all() accepts an array of promises as its argument and returns a single promise.

let myPromises = Promise.all([returnsPromOne(), returnsPromTwo(), returnsPromThree()]);
myPromises
  .then((arrayOfValues) => {
    console.log(arrayOfValues);
  })
  .catch((rejectionReason) => {
    console.log(rejectionReason);
  });

 

15. async...await

async...await is syntactic sugar built on native JavaScript promises and generators.

Inside an async function we use the await operator to pause execution of our function until an asynchronous action completes and the awaited promise is no longer pending .

async function getBeans() {
  console.log(`1. Heading to the store to buy beans...`);
  let value = await shopForBeans();
  console.log(`3. Great! I'm making ${value} beans for dinner tonight!`);
}
const shopForBeans = () => {
  return new Promise((resolve, reject) => {
	const beanTypes = ['kidney', 'fava', 'pinto', 'black', 'garbanzo'];
  setTimeout(()=>{
    let randomIndex = Math.floor(Math.random() * 5)
    let beanType = beanTypes[randomIndex];
    console.log(`2. I bought ${beanType} beans because they were on sale.`)
   resolve(beanType);
  }, 1000)
})
}
getBeans();

bash:

if no await :

 

(1) Handling Dependent Promises

With native promise syntax, we use a chain of .then() functions making sure to return correctly each one:

function nativePromiseVersion() {
    returnsFirstPromise()
    .then((firstValue) => {
        console.log(firstValue);
        return returnsSecondPromise(firstValue);
    })
   .then((secondValue) => {
        console.log(secondValue);
    });
}

Here’s how we’d write an async function to accomplish the same thing:

async function asyncAwaitVersion() {
 let firstValue = await returnsFirstPromise();
 console.log(firstValue);
 let secondValue = await returnsSecondPromise(firstValue);
 console.log(secondValue);
}

(2) Handling Independent Promises

async function waiting() {
 const firstValue = await firstAsyncThing();
 const secondValue = await secondAsyncThing();
 console.log(firstValue, secondValue);
}

In the waiting() function, we pause our function until the first promise resolves, then we construct the second promise. Once that resolves, we print both resolved values to the console.

async function concurrent() {
 const firstPromise = firstAsyncThing();
 const secondPromise = secondAsyncThing();console.log(await firstPromise, await secondPromise);
}

In our concurrent() function, both promises are constructed without using await. We then await each of their resolutions to print them to the console.

 

Note: if we have multiple truly independent promises that we would like to execute fully in parallel, we must use individual .then() functions and avoid halting our execution with await.

 

(3) Await Promise.all()

when we have multiple promises which can be executed simultaneously is to await a Promise.all().

async function asyncPromAll() {
  const resultArray = await Promise.all([asyncTask1(), asyncTask2(), asyncTask3(), asyncTask4()]);
  for (let i = 0; i<resultArray.length; i++){
    console.log(resultArray[i]); 
  }
}

 

16. Requests

See another blog for details.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章