---
# System prepended metadata

title: Javascript ES6

---

# 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/)

需要轉成真正的陣列使用，可以用上述 `...` 的做法進行