筆記

  • IE 以外瀏覽器,超過九成以上都已經支援 ES6 寫法,如果要顧及 IE ,只能透過 babel 轉譯。

  • Scope(區塊):let 所宣告的變數只能做用到代碼塊區域(block scope)中。 let in block scope let in for

// scope let, var
{
  var a = 123;
  let b = 456;
}
console.log(a);
console.log(b);


for (var a = 0; a < 5; a++) {

}
console.log(a);

for (let b = 0; b < 5; b++) {

}
console.log(b);
  • Hoisting(提升):JS 使用 var 的時候,會檢查整份 code 是否被宣告過,如果被宣告為 function 會優先使用。 var @Hoisting
// 一開始只寫 console 的時候, a 是 not defined
console.log(a);
var a = 3;
// 一旦後面寫個同名的 function,就會提升到前面,a 顯示為一個函式,function 優先權較高
function a() {
}
  • Hoisting(提升):JS 使用 let 的時候,如果是使用後才宣告,會報錯。 let @Hoisting
// 如果改成 let ,會報錯,提示需要先宣告再使用
console.log(b);
let b = 3;
function b() {
}
  • Dead Zone:在一個 scope 中,如果有用 let 做宣告,那在 let 之前都無法使用。 let @Dead Zone
var a = 'Mike';
{
  console.log(a); // Mike
  // scope 裡面可以取到外面的值
  var a = 123;
  console.log(a); // 123
}

let b = 'Mike';
{
  console.log(b); // 報錯
  let b = 123;
  console.log(b);
}
  • 使用 let 只要注意 先宣告,後使用 即可,同時避免 scope 內外宣告相同名稱或重複宣告。

  • const(常數):通常只能設定一次,後面修改會報錯。 const

const name = 'Mike';
name = 'Michelle' // 會報錯
  • const 宣告物件,物件本身無法被修改,但物件內部的參數卻可以修改。 const宣告物件
const obj = {
  name: 'Mike'
}

obj.name = 'Michelle'; // 物件內部的參數卻可以修改
console.log(obj);

obj = { // 物件本身無法被修
  name: 'Michelle'
}
  • 箭頭函式:大括號內如果只有一行可以省略大括號,箭頭函式預設會 return,所以 return 也省略。 箭頭函式
// 傳統寫法一
function abc() {
  return 'abc';
}

// 傳統寫法二:避免 Hoisting 的 function 優先問題發生,程式相對穩定
let abc = function () {
  return 'abc';
}

// 箭頭函式
let abc = () => {
  return 'abc'
};

// 大括號內如果只有一行可以省略
// 箭頭函式預設會 return,所以 return 也省略
let abc = () => 'abc';

console.log(abc());
  • 箭頭函式預設會 return » 學習 Functional Programming

  • Callback hell 中的 this 會代表不同對象。 Callback hell

  • this 問題 - 傳統 var self = this; 解法。 var self = this;

  • this 問題 - 箭頭函式解法,箭頭函式沒有自己的 this,會沿用父層的 this。但要小心本範例如果父層也用箭頭函式,this 就會指到 window。 箭頭函式解法

  • 字串模板:ES6 的 `(反引號) 可直接將 HTML 原始內容放入,支援換行。參數可以做運算、帶 function。 字串模板

let btnText = "Button";

// 傳統只有單引號與雙引號可用,有時候還要配合反斜線和加號。
let htmlTemplate1 = '<div><a href="#">' + btnText + '</a></div>';
let htmlTemplate2 = "<div><a href='#'>" + btnText + "</a></div>";
let htmlTemplate3 = "<div><a href=\"#\">" + btnText + "</a></div>";

// ES6 的 `(反引號) 可直接將 HTML 原始內容放入,支援換行。
// 參數可以做運算、帶 function
let getNum = () => {
  return Math.floor(Math.random() * 10);
};

let htmlTemplateES6 = `
      <div>
        <a href="#">${btnText + '!!! ' + getNum()}</a>
      </div>
    `;
document.body.innerHTML = htmlTemplateES6;
  • 函式 預設值 寫法。 函式預設值
// ES5 設定預設值寫法
function test1(a, b, c, d) {

  a = a || 'AAA'
  b = b || 'BBB'
  c = c || 'CCC'
  d = d || 'DDD'

  console.log(a, b, c, d);
}
console.log(test1());

// ES6 預設值寫法
function test1_ES6(a = 'AAA', b = 'BBB', c = 'CCC', d = 'DDD') {
  console.log(a, b, c, d);
}
console.log(test1_ES6());
  • 函式預設值寫法 - 物件拆解物件拆解
// ES5 設定預設值寫法
function test2(obj) {

  obj = obj || {}
  obj.a = obj.a || 'AAA'
  obj.b = obj.b || 'BBB'
  obj.c = obj.c || 'CCC'
  obj.d = obj.d || 'DDD'

  console.log(obj);
}
console.log(test2());

// ES6 預設值寫法 - 物件拆解
function test2_ES6({ a = 'AAA', b = 'BBB', c = 'CCC', d = 'DDD' }) {
  console.log(a, b, c, d);
}
console.log(test2_ES6({ a: 'Mike' }));
  • 陣列拆解 陣列拆解
let arr = [1, 2, 3, 4, 5, 6];

// let a = arr[0], b = arr[1], c = arr[2];

let [a, b, ...c] = arr;
// 頭兩個分給 a, b,剩下的都分給 c

console.log(a);
console.log(b);
console.log(c);
  • 拆解應用一 拆解應用一
let mike = {
  name: 'Mike',
  bType: 'B',
  sex: 'male'
}

let { name, bType, sex } = mike;
// import { name, bType, sex } from 'mike';
// node_modules 常看到這種用法

console.log(name, bType, sex);
  • 拆解應用二 拆解應用二
let name = 'Mike';
let sex = 'male';

// 傳統寫法:浪費人生,要打兩次?
let mike = {
  name: name,
  sex: sex
}
console.log(mike);

// ES6 寫法
let mike_ES6 = {
  name,
  sex
}
console.log(mike_ES6);

  • Promise:用來保證 function 執行的先後順序。

  • 未使用 Promise,執行順序不如預期。 未使用 Promise

  • 使用 Promise 做流程控制,把非同步做成同步。 使用 Promise

function fn1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(1);
      resolve(); // 做完事情要告訴他 resolve
    }, 0);
  })
}

function fn2() {
  console.log(2);
}

fn1().then(fn2) //依序顯示 1, 2
# 同步:依序執行,後者要等前者做完顯示結果後才能開始執行。
A[run] > A[wait] > A[finish] > B[run] > B[wait] > B[finish] > C[run] ...

# 非同步:依序執行,誰先做完就先顯示結果。
A[run] > A[wait] > A[wait] > A[wait] > A[wait] > A[finish]
       > B[run]  > B[wait] > B[finish]
                 > C[run]  > C[wait] > C[finish]
  • async/await: 屬於 ES7 的語法,基於 Promise,Generator 的升級版。同步的視覺,非同步的享受。注意 Nodejs 從 v7.6.0 才開始支援 async/await。
function fn1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(1);
      resolve(); // 做完事情要告訴他 resolve
    }, 0);
  })
}

function fn2() {
  console.log(2);
}


async function run() {
  await fn1();
  fn2();
}

run();
  • 使用 async/await 記得加上 try/catch,避免出錯。

參考