# Javascript ES6 [Notion-Page](https://yinchen.notion.site/Javascript-ES6-3186c9b234154c71adf402485c28fc25) language: javascript # `let`, `const` 變數宣告 `var` , `let` 差別一 : 如果在定義前呼叫,前者出現 `undefined` 後者出現 `not defined` ```jsx console.log(test) var test = "hello world" console.log(test2) let test2 = "hello world" ``` 名詞定義 undefined : 表示記憶體有準備位址給該變數,但變數沒有定義型態與資料 not defined : 表示記憶體沒有準備位址給變數,這變數不存在 ## `var` 作用域 : function scope,表示在函式內皆可取到 `var` 所定義的值,包含 global scope (想成就在全域函式內) ```jsx function tryIt(){ var test = "Hello, world"; if (true){ var test = "Good bye"; } console.log(test); } tryIt(); ``` 由於 `var` 是看整個作用域,所以從定義為 Hello, world 到 `if()` 變成 Good bye ## `let` 作用域 : block,即使用 `{}` 進行限制的區域內定義,這也表示其實在 global scope 不適合用 `let` ```jsx function tryIt(){ let test = "Hello, world"; if (true){ let test = "Good bye"; } console.log(test); } tryIt(); ``` 由於 `let` 在 `if()` 用 `{}` ,則使得變數被限制在內部,所以這邊會印出 Hello, world 這邊要修正成 ```jsx function tryIt(){ let test = "Hello, world"; if (true){ test = "Good bye"; } console.log(test); } tryIt(); ``` 即可印出 Good bye --- `setTimeout` 為非同步事件,會等外部程式執行完後才執行,下方 A 程式區與 B 程式區的 `i` 變數是同樣執行結果,最後在setTimeout裡 `i = 10` A 區會執行10次 ## Function Scope A 程式 ```jsx for (var i = 0; i < 10; i++){ console.log(i); setTimeout(function(){ console.log("The " + i + " turn"); }); } ``` B 程式 ```jsx for (var i = 0; i < 10; i++){ console.log(i); } setTimeout(function(){ console.log("The " + i + " turn"); }); ``` 這邊 `var` 使得 `i` 為全域變數,可以用 `window.i` 得知,因此 `setTimeout` 是 call 全域變數 調整作法有以下兩種: ```jsx // 1. for (var i = 0; i < 10; i++){ console.log(i); setTimeout(console.log("The " + i + " turn"), 10); } // 2. for (var i = 0; i < 10; i++){ console.log(i); (function(i){ setTimeout(function(){ console.log("The "+ i + " turn"); }); })(i); }; ``` 如果將 `setTimeout` 改成立即函式則可以順利執行,但是由於是立即函式,即使有寫延遲秒數依然立刻執行,兩種做法差在輸出不同 [談談 JavaScript 的 setTimeout 與 setInterval](https://kuro.tw/posts/2019/02/23/%E8%AB%87%E8%AB%87-JavaScript-%E7%9A%84-setTimeout-%E8%88%87-setInterval/) ## Block Scope D 程式 ```jsx for (let i = 0; i < 10; i++){ console.log(i); setTimeout(function(){ console.log("The " + i + " turn"); }); } ``` 由於 `let` 限制了 `i` 在 block 裡,所以會正確的依序執行 --- ## `const` 會將變數固定,不可以再次更改,但是如果是定義物件則可以更變物件裡面的值,可以用 `const` 定義初始空物件,但不能定義空矩陣或再次清空物件 ```jsx const test = "hello, world"; test = "Good bye"; // 出錯 const box = { name: "my box", things: ["book", "pen", "mouse"], descript: "I don't know" }; console.log(box); box.name = "your box"; console.log(box); box = {}; // 出錯,意義為你改變 box 的指向,所以 const 報錯 const emptyBox = {}; console.log(emptyBox); emptyBox.nothings = "not"; console.log(emptyBox.nothings); const emptyAarray = []; console.log(emptyArray); // 出錯 ``` ## 任務練習 [https://codepen.io/yinchengchen/pen/poPNrmp?editors=0011](https://codepen.io/yinchengchen/pen/poPNrmp?editors=0011) # `Array` 串接 早先的作法 用 `concat()` ```jsx let groupA = ["apple", "grape"]; let groupB = ["vegetables", "carrot"]; let groupAll = groupA.concat(groupB); console.log(groupAll); ``` 新的做法 `...` 就是把東西一個一個抓出來放進去 ```jsx let groupA = ["apple", "grape"]; let groupB = ["vegetables", "carrot"]; let groupAll2 = [...groupA, ...groupB]; console.log(groupAll2); ``` --- # 參數 : 類陣列 Array-like > 類陣列是指以數值索引的值所成的群集,它可能是串列但並非真正的陣列,例如:DOM 物件操作後所得到的串列、函式引數所形成的串列(ES6 已棄用)。 — [Reference](https://cythilya.github.io/2018/10/12/values-array-string-number/) 需要轉成真正的陣列使用,可以用上述 `...` 的做法進行