# 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/)
需要轉成真正的陣列使用,可以用上述 `...` 的做法進行