ES6 概念
ECMAScript 是 JavaScript 的一種語言標準。ES6 代表著 ECMAScript6 這個版本。
支援的瀏覽器
ECMAScript 6 ( ES6 ) 於 2015 年發布,支援的瀏覽器可參考 ECMAscript ES6 支援表
參考資料:[ES6] Javascript 開發者必須知道的 10 個新功能
ES6 新語法
let
& const
:新的變數宣告方法
- let 及 const 都是區塊作用域 block scope
- 相較於 ES5 的變數宣告只有 var,let 跟 const 的作用域有所不同。
const
當變數是個常數(不會改變),它不會被重新賦值,就可以使用 const 來宣告
- 對於 原始型態 的變數,基本上就是宣告後就不能再改變數值
- 對於 物件型態 的變數,不能變的是 記憶體位置 ,裡面的內容還是可以變的
- 所以可以改物件裡面的內容,但不能重新賦值一個新的物件
const pi = 3.14 const button = document.querySelector('btn')
- 所以可以改物件裡面的內容,但不能重新賦值一個新的物件
let
未宣告之前不可以使用:相較於 var 會有變數提升 ( Hoisting ) 的特性( 變數可以在宣告前使用,值為 undefined ), let 在宣告之前不能使用。
console.log(name); // undefined var name = 'Anbulent'; console.log(dog); // 錯誤:dog is not defined let dog = 'Lucky';
塊級作用域: var 的變數會存活在整個 function 的範圍之中,而 let 跟 const 作用域是在大括號 { } 裡面(也就是說在 if 裡面宣告的變數,在 if 之外就抓不到了),可以避免污染到其他的變數
if (true) { var dog = 'Lucky'; let name = 'Anbulent'; const PI = 3.14; } console.log(dog); // Lucky console.log(name); // 錯誤: name is not defined console.log(PI); // 錯誤: PI is not defined
Template Literals 模板字串符
- 可用於字串拼接
- 或隔行字串(以往多行字串結尾都要加上 \n 換行,再加上一堆引號跟加號,非常難閱讀)
// 字串拼接,將變數 放入 ${ } 之中
console.log(`${name}'s dog is ${dog}.`);
// ES5
var str = '開頭\n' +
'多行字串\n' +
'結束';
console.log(str);
// ES6
var str2 = `開頭
多行字串
結束`;
console.log(str2);
- 可以在模板字串符中使用函式
- 甚至可以在模板字串符的函式中寫判斷式
// 用 ${} 來使用函式
let newUl = `
<ul>
${people.map(person => `<li>我叫做 ${person}</li>`).join('')}
</ul>
`
// 在函式中加入判斷式
const people = [
{
name: '老大',
friends: 2
},
{
name: '老二',
friends: 16
},
{
name: '老么',
friends: 0
}
]
let newUl = `
<ul>
${people.map((person) => {
if (person.friends) {
return `<li>${person.name} 有 ${person.friends} 朋友</li>`
} else {
return `<li>${person.name} 沒朋友</li>`
}
}).join('')
}
</ul>
`
console.log(newUl);
// <ul>
// <li>老大 有 2 朋友</li><li>老二 有 999 朋友</li><li>老么 邊緣人</li>
// </ul>
Destructuring 解構
通過匹配 array 中的第 n 值,或是 object 內對應的 key 的值,賦值到變數,可以同時做到「變數宣告」和「變數賦值」兩件事情。
// 陣列 ------
let arr = [1, 2, 3, 4, 5];
let [first, second] = arr; // 變數對應到 arr 的 序
console.log(first); // 1
console.log(second); // 2
// 物件 ------
let obj = {
name: 'Alex',
dog: 'Lucky',
family: {
father: 'Peter'
}
}
let {name, dog} = obj; // 變數要對應到 obj 的 key
let {family: {father}} = obj; // 也可以對應到更裡面,但只會取出最深處的變數,此例是 father
console.log(name); // Alex
console.log(dog); // Lucky
console.log(father); // Peter
console.log(family); // 錯誤:family is not defined
/* 舊的 ES5 寫法 ---
var first = arr[0];
var second = arr[1];
var name = obj.name;
var dog = obj.dog;
var father = obj.family.father;
-------------------
*/
陣列是使用順序的索引值對應,但物件則是使用物件的屬性名稱來做對應(因此沒有順序性)。
解構的好處 是提取 JSON 的時候很方便
let ajax_JSON = {
id: 9527,
name: 'Kanboo',
other: {
tel: '1234567',
fax: '7654321'
}
};
let {
id,
name,
other: { tel }
} = ajax_JSON;
console.log(id, name, tel); // 9527 "Kanboo" "1234567"
Spread Operator 展開運算子
展開運算子是 ”把一個陣列展開(expand)成個別數值“ 的速寫語法,簡單來說,就是 把陣列裡面的值,拆解成一個一個。
let arr2 = ['a', 'b'];
let arr3 = ['c', 'd'];
console.log([...arr2, ...arr3]); // [ 'a', 'b', 'c', 'd', 'e' ]
console.log(['new', ...arr2, 'last']); // [ 'new', 'a', 'b', 'last' ]
arr2.push(...arr3);
console.log(arr2); // [ 'a', 'b', 'c', 'd' ]
let name = [...'Alex'];
console.log(name); // [ 'A', 'l', 'e', 'x' ]
let obj = {name : 'Alex'}
let obj2 = {...obj};
console.log(obj2); // { name: 'Alex' }
console.log(obj === obj2); // false,記憶體位置不同
Rest Parameters 其餘運算子
// 可傳入不固定的參數,1個 or 多個 皆可…
function sum(...numbers) {
var result = 0;
numbers.forEach(function (number) {
result += number;
});
return result;
}
//傳入一個值
console.log(sum(1)); // 1
//傳入多個值
console.log(sum(1, 2, 3, 4, 5)); // 15
let arr = [1, 2, 3, 4, 5];
let [first, second, ...rest] = arr;
console.log(...rest); // 3, 4, 5
let obj = {
a: 1,
b: 2,
c: 3
}
let {a, ...obj2} = obj; // ...集合
console.log(a, obj2); // 1 { b: 2, c : 3 }
let obj3 = {
...obj2, // ...展開
d: 4
}
console.log(obj3); // { b: 2, c: 3, d: 4 }
- 其餘參數(Rest parameters)有一個限制,就是這個參數一定是函式的「最後一個」。(如果放在其餘的參數前,就會產生錯誤)
Default Parameters 參數預設值
// 可以幫函式的參數加上預設值
function whosDog(name = 'Alex', dog = 'Lucky'){
return `${name}'s dog is ${dog}`;
}
console.log(whosDog()); // Alex's dog is Lucky
console.log(whosDog('小明', '小花')); // 小明's dog is 小花
// 也可以搭配解構使用,幫不存在的 c 丟入預設值
let obj = {
a: 1,
b: 2
}
let {a = 'a', b = 'b', c = 'c'} = obj;
console.log(a, b, c); // 1 2 'c'
Arrow Function 箭頭函式
一般使用箭頭函式與 function 的用法大致一致,可以傳入參數、也有大括號包起來
- 只有一個回傳值,可以省略 return ( 但是如果有寫大括號 {} 就得加上 return,如果沒有傳入值則會出現 undefined)
- 只有一個參數,可以省略括號 ( )
// 正常寫法
var callSomeone = (someone) => {
return someone + '上工了'
}
console.log(callSomeone('伙計'))
// 縮寫,單一行陳述不需要 {}
var callSomeone = (someone) => someone + '上工了'
console.log(callSomeone('伙計'))
// 只有一個參數可以不加括號
var callSomeone = someone => someone + '上工了'
console.log(callSomeone('伙計'))
// 沒有參數時,一定要有括號
var callSomeone = () => '伙計' + '上工了'
console.log(callSomeone('伙計'))
// 有寫大括號 {} 就一定要加上 return
var callSomeone = (someone) => { someone + '上工了' }
console.log(callSomeone('伙計')) // undefined
實用的操作方式
let arr = [1, 2, 3, 4, 5] .filter(value => value > 1) .map(value => value * 2); console.log(arr); // [ 4, 6, 8, 10 ]
補充:箭頭函式裡面的this 等於 外面的this
箭頭函式裡的this 主要是依據 外層函式(function)裡的this 是什麼就跟著是什麼。
ES6模組的輸出與輸入
使用 export
加在在想要輸出部分的前面,物件、類別、函式與原始資料(變數與常數)都可以輸出
// 分開來一個一個輸出
export const aString = 'test'
export function aFunction(){
console.log('function test')
}
export const aObject = {a: 1}
export class aClass {
constructor(name, age){
this.name = name
this.age = age
}
}
// 用 { } 包起來一起輸出
const add = (a, b) => a + b;
const PI = 3.14;
export {
add,
PI
}
有兩種方式可以進行輸入,一種是每個要輸入的名稱都需要定在在花括號({}
)之中,另一種是用 *
,但要自行定義一個模組名稱(避免命名衝突)
// 使用 {} 將要引入的東西寫在裡面
import {aString, aObject, aFunction, aClass} from './lib.js'
console.log(aString)
console.log(aObject)
// 使用 * 全部引入,自行定義一個模組名稱叫做 myModule
import * as myModule from './lib.js'
console.log(myModule.aString)
console.log(myModule.aObject)
myModule.aFunction()
const newObj = new myModule.aClass('Inori', 16)
console.log(newObj)
Babel
Babel 是一個 JavaScript 的轉譯器,可以幫你轉成需要的版本、輕鬆解決以上問題,意思是你依舊可以使用潮潮的最新語法,而不用為了使用者環境而吐血。
- 設定步驟:
- 安裝必要套件:
npm install --save-dev @babel/core @babel/node @babel/preset-env
- 新增 Babal 的設置檔:
.babelrc
- 在
.babelrc
裡輸入以下內容,告訴 babel 要用這個 preset:{ "presets": ["@babel/preset-env"] }
- 最後使用
npx babel-node <index.js>
運行即可
- 安裝必要套件:
參考資料:
[筆記] JavaScript ES6 中的模版字符串(template literals)和標籤模版(tagged template)
Webpack教學 (四):JavaScript 與 Babel