# ES6 的一些常用新語法
###### tags: `JavaScript` `ES6`
## var, let, const
### var 宣告變數(ES5)
> var 宣告變數時,它的作用範圍可以是全域也可以是區域,但如果使用區塊語句(ex: if, else, for, while)時,宣告的區域變數仍然可在作用範圍外被存取
#### 情境一
> var 一個全域變數可在 function 內/外使用、可被存取與修改
```
var i = 3;
(function () {
i += 1;
})();
console.log(i); // 輸出結果為 4
```
#### 情境二
> var 一個區域變數執行結束後就會失效,故在 function 外取 *j* 的值是 undefined
```
(function () {
var j = 4;
j += 1;
})();
console.log(j); // 輸出結果為 j is not defined
```
#### 情境三(宣告與不宣告)
> 若無宣告,則其變數會被當成全域變數
```
(function x() {
y = 1; // 無宣告,因此被作為全域變數使用
var z = 2;
})();
console.log(y); // 為全域變數,所以 y = 1
console.log(z); // 為區域變數,所以 z 未被找到
```
### let 變數宣告(ES6)
> let 可以只宣告在目前作用的區塊、階段或表達式中作用的變數
#### 範例
```
let x = 1;
if (x === 1) {
let x = 2;
console.log(x); // 會輸出 2
}
console.log(x); // 會輸出 1
```
### let 與 var 差異比較
#### 情境一 (在 if 中分別使用 var 與 let 宣告)
* var ( if 跑完後,在區塊語句外可以輸出 *b* )
```
if (true) {
var b = 20;
}
console.log(b); // 輸出值為 20
```
* let ( if 跑完後,在區塊語句外無法輸出 *b* )
```
if (true) {
let b = 20;
}
console.log(b); // 會輸出 b is not defined
```
#### 情境二(在 function 區塊與子區塊中宣告)
* var
```
(function varTest() {
var x = 1;
{
var x = 2; // 這裡的x是一樣的,會改變整個 function 的 x
console.log(x); // 輸出值為 2
}
console.log(x); // 輸出值為 2
})();
```
* let
```
(function letTest() {
let x = 1;
{
let x = 2; // 這裡的 x 是不同的,只會作用在這層區塊中
console.log(x); // 輸出 2
}
console.log(x); // 輸出 1
})();
```
### const(ES6)
const 會對於它的值建立一個唯讀的參考( const 宣告時一定要有值,否則會跳錯誤)。並不是說這個值不可變更,而是這個變數不能重新指定值,例如常數的內容(值)是個物件,那麼此物件的參數是可以更改的。它與 let 一樣都是可以只宣告在目前作用的區塊
#### 情境一(宣告一個常數)
```
const firstName = 'HSU';
// 測試 1
firstName = 'LIN'; //Error: firstName 已經分配給常數
// 測試 2
const firstName = 'LIN'; //Error: firstName 已經被宣告過
// 測試 3
let firstName = 'LIN'; //Error: firstName 已被宣告
```
#### 情境二(宣告常數為一個物件)
```
const room = [{
teacher: 'Lin',
students: 30
},
{
teacher: 'Wang',
students: 36
}
]
room[0].teacher = 'Chen';
console.log(room[0].teacher); //會輸出 Chen
```
## Arrow Functions(箭頭函式)
> 讓匿名函式寫法更簡略,寫法為 `( ) => { }` ,如果只有一行語句的話可以省略大括號,它會自動 `return` ,但也只能在只有一行語句的時候使用。
> 使用大括號 `{ }` 則是可以加入多行的語句,不過不會自動 `return` ,有需要的話要自己加上,如果沒加 `return` 的話,之後執行會輸出 undefined。
### JavaScript(ES5)
```
var count = function(a, b){
return a * b;
}
count(2, 5);
```
### JavaScript(ES6)
#### 情境一(只有一個參數)
> 當函數只有一個參數時,不需要使用括號
```
// 原
let count = (a) => { return a + 1; };
// 可寫成
let count = a => a + 1;
count(5); // 會輸出 6
```
#### 情境二(兩個以上的參數)
```
let count = (a, b) => a * b;
count(2, 6); // 會輸出 12
```
## Template Literals(模板文字)
> 在 String 內嵌入變數時,在 ES5 中必須把字串拆散,通過" + "字元加入字串; 而在 ES6 中,變數被容許通過語法 ${value} 加在字串中,但是需被" ` " (反引號)包在裡面而不是單/雙引號
### Expression interpolation
#### JavaScript(ES5)
```
var a = 5;
console.log('Five is ' + a + '.');
```
#### JavaScript(ES6)
```
let a = 5;
console.log(`Five is ${a} .`);
```
### Multi-line Strings(多行字串符)
#### JavaScript(ES5)
> ES5 中,若字串要換行需加 \n
```
let str="line1";
let str2="line2";
console.log( str+'\n' +
str2);
```
#### JavaScript(ES6)
> ES6 中,只要用反引號包起來,再根據要換行的地方做換行動作就好
```
let str="line1";
let str2="line2";
console.log(`str
str2`);
```
參考來源:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
https://wcc723.github.io/javascript/2017/12/21/javascript-es6-arrow-function/