前言 ES6 核心知識點學習整理記錄
目錄
本章分享的ES6語法核心常用知識點開發必會 - 面試必備;
- let , const
- 解構賦值
- 字符串,正則,數組,對象,函數的擴展 + Symbol
- Set , Map 數據結構、
- Proxy 代理 / 攔截 , Reflect
- Generator 函數
- async 函數
- Promise對象
- class 類
- module 模塊兒
針對ES6的知識點做一個簡要的概述與實踐,常用核心的知識點會講述的稍微細一點,其它的都是略帶過,我也是奮鬥在學習中的小白,望各位大佬多多建議。
let , const
ES6新增了let,const 命令,用來聲明變量。它的用法類似於var;
let
let聲明一個塊級變量
1,不存在變量提升 n = 10;let n ; // 報錯,告訴你let聲明要放在前邊
2,只在聲明的代碼塊兒內有效 {let n = 1; var m = 2} // n is not defined , m // 2
3,不允許重複聲明 {let n = 1; let n;} // 控制檯會報錯,不讓重複聲明
const
const聲明一個只讀的常量。一旦聲明,常量的值就不能改變;
1,常量聲明之後不能修改 const n = 10 ; n = 101; // 控制檯會發生報錯告訴你不能修改常量
2,同樣不存在變量提升 //可參考let
3,不能重複聲明 //可參考let
4,如果聲明一個數組或者對象,則能操作寫值,不能直接賦值,看例子
const arr = [];
arr.push(1) // [1]
arr[1] = 2 // [1,2]
arr = [1,2,3] // 控制檯會報錯, 告訴你常量不能賦值
解構賦值
官方解釋:ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。
粗魯的講:就是解開變量的結構去給對應的結構賦值,哈哈哈,通過一個簡單的例子來表達一下
var a = 1;
var b = 2;
var c = 3;
// ES5簡化一點
var a = 1, b = 2, c = 3;
// ES6寫成下面這樣
var [a, b, c] = [1, 2, 3];
是不是好容易,這就是模式匹配,只要兩邊的結構模式一樣,左邊的變量就會賦右邊對應的值,我們再來看幾種情況
數組的解構賦值
let [a, [[b], c]] = [1, [[2], 3]];
a // 1
b // 2
c // 3
let [ , , c] = ["a", "b", "c"];
c // "c"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [x, ...arr] = [1, 2, 3, 4];
x // 1
arr // [2, 3, 4] ... 我們後邊要說的 展開運算符
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
對象的解構賦值
var { a, b} = { a: "aaa", b: "bbb" };
a // aaa
b // bbb
var { b, a } = { a: "aaa", b: "bbb" };
a // "aaa"
b // "bbb"
var { c } = { a: "aaa", b: "bbb" };
c // undefined
// 看一個擴展,上邊的 var {a,b} = { a: "aaa", b: "bbb" } ; 實際上就是下邊這種形式
var { a: a, b: b } = { a: "aaa", b: "bbb" };
a // aaa
b // bbb
//我們換一種方式
var { a: aa, b: bb } = { a: "aaa", b: "bbb" };
a // a is not defined
b // a is not defined
// --- 分割線 ---
aa // aaa
bb // bbb
// 可看出來真正的結果還是 key:value 的value,並不是 key
還有 字符串,布爾值,函數的解構賦值方式,我就不一一列舉出來了,
總結
- 簡化變量聲明,快捷,方便
- 簡化數組,對象操作
- 函數參數默認賦值操作
- 等號左邊模式與右邊值不匹配則默認輸出 undefined 或者 xx is not defined
字符串,正則,數組,對象,函數的擴展 + Symbol
說到這些類型的擴展就更是讓人心曠神怡了,爲什麼這樣說,因爲看過官方文檔的小夥伴們肯定都驚呆了,各種神操作,各種簡化,各種爽,有一句話說的好,一直加班一直爽,在這裏我就想說:一直擴展一直爽。
數組的擴展
Array.from()
Array.from方法用於將兩類對象轉爲真正的數組:類似數組的對象(array-like object)和可遍歷(iterable)的對象(包括ES6新增的數據結構Set和Map)。
1,下面是一個類似數組的對象,Array.from將它轉爲真正的數組。
var arr = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的寫法
var arr1 = [].slice.call(arr); // ['a', 'b', 'c']
// ES6的寫法
let arr2 = Array.from(arr); // ['a', 'b', 'c']
再來看一個例子
// Map 對象 ES6 新增後邊會講到
var map = new Map()
map // Map(0) {}
Array.from(map) // []
// Set 對象 ES6 新增後邊會講到
var set = new Set()
set // Set(0) {}[[Entries]]No propertiessize: (...)__proto__: Set
Array.from(set) // []
2, Array.from() 還提供了類似 .map 的回調函數
var arr = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
let arr = Array.from(arr,(i,n) => {
// 回調函數類似於 arr.map( () => { ... } )
});
Array.of()
Array.of方法用於將一組字符串值,轉換爲數組
Array.of(1, 2, 3) // [1,2,3]
Array.of(1) // [1]
Array.of(1).length // 1
entries(),keys() ,values()
這三個常用於對數組實例的遍歷。可以用 for…of 循環遍歷
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
keys()是對鍵名的遍歷、values()是對鍵值的遍歷,entries()是對鍵值對的遍歷。
展開符 …
let arr = [1,2,3,4]
console.log(...arr) // 1 2 3 4
//合併數組
let arr2 = [5]
let concat = [...arr,...arr2] // (5) [1, 2, 3, 4, 5]
//其實主要就是一個數組展開運算符
函數的擴展
函數參數默認值
// 引用官方的樣例
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
作用域
// 引用官方的樣例
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
// 調用函數 f 的時候,變量x有自己的獨立作用域
// 緊跟着 y = x
// 然後打印 y 輸出 2
再看另外一種
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
// 全局聲明 x
// 函數 f 給 變量 y 默認賦值 x , 此時 x = 1;
// 函數 f 體內聲明局部變量 x
// 打印 y , y 等於默認賦值 x , 固 輸出 1
// 如果全局 x 沒有聲明呢, 那麼就會報錯
箭頭函數
相信用過 vue / react 框架的應該都用到了箭頭函數這個概念吧。通過一個簡單的例子來認識一下
var f = () => 5;
// 等同於
var f = function () { return 5 };
//--------
var sum = (num1, num2) => num1 + num2;
// 等同於
var sum = function(num1, num2) {
return num1 + num2;
};
看得出來,其實是對ES5函數的一種簡寫方式,讓語法更簡介,更明瞭,再通過一個例子來看一下
let getNumber= num => ({ num: num, name: "tom" });
//轉換成 es5 就是
var getNumber = function (num) {
return {
num: num,
name: "tom"
}
}
//注意,如果需要直接返回一個對象,需要用()括號括起來,否則會報錯
通過幾個簡單的例子就可以明白ES5函數與ES6函數使用的區別了,那咋這裏呢,其實ES6 的使用還是有一些需要注意的地方的,
1,函數體內的this對象,指向定義時所在的對象,而不是使用時所在的對象。其實箭頭函數是沒有 this 的概念的,所以在箭頭函數中 this 的指向是不會變的。
2,不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
3,不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest (es6 新增)
對象的擴展
ES6 允許在大括號裏面,直接寫入變量和函數,作爲對象的屬性和方法。這樣的書寫更加簡潔。
變量
const x = 'x';
const y = {x};
y // {x: "x"}
// 等同於
const y = {x: x};
函數
function f(x, y) {
return {x, y};
}
// 等同於
function f(x, y) {
return {x: x, y: y};
}
f(1, 2) // Object {x: 1, y: 2}
屬性的遍歷方式
ES6 一共有 5 種方法可以遍歷對象的屬性
// 常用
for...in
// for...in循環遍歷對象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。
Object.keys(obj)
// Object.keys返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)的鍵名。
// 不常用的
Object.getOwnPropertyNames(obj)
//Object.getOwnPropertyNames返回一個數組,包含對象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)的鍵名。
Object.getOwnPropertySymbols(obj)
//Object.getOwnPropertySymbols返回一個數組,包含對象自身的所有 Symbol 屬性的鍵名。
Reflect.ownKeys(obj)
//Reflect.ownKeys返回一個數組,包含對象自身的所有鍵名,不管鍵名是 Symbol 或字符串,也不管是否可枚舉。
Set , Map 數據結構
Set
ES6 提供了新的數據結構 Set。它類似於數組,但是成員的值都是唯一的,沒有重複的值,先來認識它一下
const s = new Set();
s
Set(0) {}
[[Entries]]
No properties
size: (...)
__proto__: Set
add 方法,用於添加一個元素
s.add(1)
Set(1) {1}
s
Set(1) {1}[[Entries]]
0: 1
size: (...)
__proto__: Set
// 可以看到 s 對象裏有一條數據了 0 : 1
向 Set 加入值的時候,不會發生類型轉換;
說到類似數組 or 沒有重複的值,瞬間我們是不是就想到了前端經典面試題,實現一個數組去重
Set函數可以接受一個數組
const set = new Set([1, 2, 3, 4, 4]);
set // Set(4) {1, 2, 3, 4}
[[Entries]]
0: 1
1: 2
2: 3
3: 4
size: (...)
__proto__: Set
可以看到 set 返回一個類似數組的對象 , 那麼如何轉換成真正的數組格式呢
ES6 常見的有兩種方式,上邊我們都有介紹過
const set = new Set([1, 2, 3, 4, 4]);
[...set] // [1, 2, 3, 4]
Array.from(set) // [1, 2, 3, 4]
Set 實例的屬性和方法
Set.prototype.constructor:
構造函數,默認就是Set函數。
Set.prototype.size
:返回Set實例的成員總數。
Set 實例的方法分爲兩大類:操作方法(用於操作數據)和遍歷方法(用於遍歷成員)。下面先介紹四個操作方法。
Set.prototype.add(value)
:添加某個值,返回 Set 結構本身。
Set.prototype.delete(value)
:刪除某個值,返回一個布爾值,表示刪除是否成功。
Set.prototype.has(value)
:返回一個布爾值,表示該值是否爲Set的成員。
Set.prototype.clear()
:清除所有成員,沒有返回值。
Map
JavaScript 的對象(Object),本質上是鍵值對的集合(Hash 結構),但是傳統上只能用字符串當作鍵,這給它的使用帶來了很大的限制。
其實Map 解構跟 Set 也挺相似,我們來認識一下Map結構
const m = new Map();
m
Map(0) {}
[[Entries]]
No properties
size: (...)
__proto__: Map
Map 數據結構的增刪方法
// 引用官方的樣例
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
上面代碼使用 Map 結構的set方法,將對象o當作m的一個鍵,然後又使用get方法讀取這個鍵,接着使用delete方法刪除了這個鍵。
Map 數據解構也可以接收一個數組作爲參數,例如:
const map = new Map([
['name', '張三'],
['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "張三"
map.has('title') // true
map.get('title') // "Author"
其實傳入一個數組作爲參數,背後只是執行了一次遍歷,new 了多次 Map
const items = [
['name', '張三'],
['title', 'Author']
];
const map = new Map();
items.forEach(
([key, value]) => map.set(key, value)
);
那麼Map 有什麼不一樣的呢 , 到底解決了什麼問題,通過下邊這個例子來看一下
const aa = new Map();
aa.set({obj:'obj 鍵值對相當key'},"123")
Map(1) {{…} => "123"}
[[Entries]]
0: {Object => "123"}
key: {obj: "obj 鍵值對相當key"} // 重點 key
value: "123" // 重點 value
size: (...)
__proto__: Map
官方解釋:
JavaScript 的對象(Object),本質上是鍵值對的集合(Hash 結構),但是傳統上只能用字符串當作鍵,這給它的使用帶來了很大的限制。
Map 解決:
爲了解決這個問題,ES6 提供了 Map 數據結構。它類似於對象,也是鍵值對的集合,但是“鍵”的範圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。也就是說,Object 結構提供了“字符串—值”的對應,Map 結構提供了“值—值”的對應,是一種更完善的 Hash 結構實現。
Map的實例屬性和方法
Map.prototype.set(key, value)
set方法設置鍵名key對應的鍵值爲value,然後返回整個 Map 結構。如果key已經有值,則鍵值會被更新,否則就新生成該鍵。
Map.prototype.get(key)
get方法讀取key對應的鍵值,如果找不到key,返回undefined。
Map.prototype.has(key)
has方法返回一個布爾值,表示某個鍵是否在當前 Map 對象之中。
Map.prototype.delete(key)
delete方法刪除某個鍵,返回true。如果刪除失敗,返回false。
Map.prototype.clear()
clear方法清除所有成員,沒有返回值。
應用場景:
Set :很顯然,我們上邊就說到了經典的數組去重
Map :也很顯然,解決了鍵值對,“鍵” 可以多種類型方式
Proxy
Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這裏表示由它來“代理”某些操作,可以譯爲“代理器”
通過官方的一例子先來認識一下 proxy
var obj = new Proxy({}, {
get: function (target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
console.log(`setting ${key}!`);
return Reflect.set(target, key, value, receiver);
}
});
//上面代碼對一個obj對象架設了一層攔截,重定義了屬性的讀取(get)和設置(set)行爲
obj.a = 1
// VM888:7 setting a!
obj.a // 1
++obj.a
// VM888:3 getting a!
// VM888:7 setting a!
obj.a // 2
可以發現:我們攔截了obj.a 的獨寫操作。
基本語法
var proxy = new Proxy(target, handler);
new Proxy()
表示生成一個Proxy實例,
target
參數表示所要攔截的目標對象,
handler
參數也是一個對象,用來定製攔截行爲。
在這裏訪問 proxy 就相當於訪問 target 目標對象,例如:
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"
擴展屬性:Proxy 支持的攔截操作
get(target, propKey, receiver)
// 攔截對象屬性的讀取,比如proxy.foo和proxy['foo']。
set(target, propKey, value, receiver)
// 攔截對象屬性的設置,比如proxy.foo = v或proxy['foo'] = v,返回一個布爾值。
has(target, propKey)
// 攔截propKey in proxy的操作,返回一個布爾值。
deleteProperty(target, propKey)
// 攔截delete proxy[propKey]的操作,返回一個布爾值。
ownKeys(target)
// 攔截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)for...in循環,返回一個數組。該方法返回目標對象所有自身的屬性的屬性名,而Object.keys()的返回結果僅包括目標對象自身的可遍歷屬性。
getOwnPropertyDescriptor(target, propKey)
// 攔截Object.getOwnPropertyDescriptor(proxy, propKey),返回屬性的描述對象。
defineProperty(target, propKey, propDesc)
// 攔截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一個布爾值。
preventExtensions(target)
// 攔截Object.preventExtensions(proxy),返回一個布爾值。
getPrototypeOf(target)
// 攔截Object.getPrototypeOf(proxy),返回一個對象。
isExtensible(target)
// 攔截Object.isExtensible(proxy),返回一個布爾值。
setPrototypeOf(target, proto)
// 攔截Object.setPrototypeOf(proxy, proto),返回一個布爾值。如果目標對象是函數,那麼還有兩種額外操作可以攔截。
apply(target, object, args)
// 攔截 Proxy 實例作爲函數調用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args)
// 攔截 Proxy 實例作爲構造函數調用的操作,比如new proxy(...args)。
Generator 函數
Generator 函數是 ES6 提供的一種異步編程解決方案,語法行爲與傳統函數完全不同。
我們先來認識一下 Generator 函數
1,function關鍵字與函數名之間有一個星號;
2,函數體內部使用yield表達式,定義不同的內部狀態
Generator 函數的調用方法與普通函數略不一樣,普通函數調用只是 fun()
而Generator函數只是在這個基礎之上需要 .next()
也就是 fun().next()
使得指針移向下一個狀態;也就是說,每次調用next方法,內部指針就從函數頭部或上一次停下來的地方開始執行,直到遇到下一個yield表達式(或return語句)爲止。換言之,Generator 函數是分段執行的,yield表達式是暫停執行的標記,而next方法可以恢復執行。
看過我 Javascript 進階文章二的小夥伴應該知道函數柯里化,感覺有點類似,GO Javascript 進階二
下邊來看一個實際的例子
function* Gen () {
yield 'Hi';
yield 'Sen';
return "HiSen";
}
var G = Gen()
G.next()
{value: "Hi", done: false}
G.next()
{value: "Sen", done: false}
G.next()
{value: "HiSen", done: true}
G.next()
{value: undefined, done: true}
結果顯而易見:
變量 G
等於 函數 Gen()
,G.next()
執行進入下一個狀態,每次返回一個對象,它的value屬性就是當前yield表達式的值 ,done屬性的值false,表示遍歷還沒有結束。依次執行G.next()
返回對應對象,執行到 return 代碼時返回最終結果 {value: "HiSen", done: true}
再執行返回 {value: undefined, done: true}
。
總結,調用 Generator 函數,返回一個遍歷器對象,代表 Generator 函數的內部指針。以後,每次調用遍歷器對象的next方法,就會返回一個有着value和done兩個屬性的對象。value屬性表示當前的內部狀態的值,是yield表達式後面那個表達式的值;done屬性是一個布爾值,表示是否遍歷結束 。
async await
async 函數是什麼?一句話,它就是 Generator
函數的語法糖。async
和await
,比起星號和yield
,語義更清楚了。async
表示函數裏有異步操作,await
表示緊跟在後面的表達式需要等待結果(異步任務)。
基本用法:
函數前面有一個async關鍵字,表明該函數內部有異步操作。調用該函數時,會立即返回一個Promise對象
Promise
後邊我會講到。await
一般使用在 async
函數內部 。
通過一個簡單的例子先來認識一下 async
函數
async function as () {
return 2;
}
as()
// Promise {<resolved>: 2}
可以看到返回一個 promise 對象,並且默認 resolved 成功回調傳參 2 ,可以得出結論,async函數內部return語句返回的值,會成爲then方法回調函數的參數。
接下來我們來認識一下 await
,正常情況下,await命令後面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值。接下來我們實踐一下
function setTime () {
return new Promise(function (resolve,reject) {
setTimeout(
function () {
resolve("成功")
},2000)
})
}
setTime() // 返回一個 Promise {<pending>} 對象
// await 接受一個 promise 對象 , 這裏我們分離出去使用 setTime 函數。
async function as () {
var num = 1;
num = await setTime(); // await 後邊跟一個 promise 對象
console.log(num)
}
as() // Promise {<pending>} 2秒之後返回 "成功"
分析:
setTime 函數返回一個 promise
對象,2秒之後成功回調 resolve("成功")
,
然後我們定義一個 async await 形式的函數 as ,來簡單實現一下如何解決解異步編程,
1,聲明變量 num
初始化 1,
2,await setTime()
表示需要等待 setTime()
的結果,才往下走
3,所以2秒後打印 成功
一個簡單的 async await 函數就這樣出現在大家的眼前,是不是很簡單,很神奇,代碼看起來就是完完全全的同步操作。聲明變量,變量賦值,打印變量,但是裏邊卻包含着異步任務。其實await命令後面,可以是 Promise 對象和原始類型的值(數值、字符串和布爾值,但這時會自動轉成立即 resolved 的 Promise 對象
。
Promise
上邊我們說到 Promise 對象,那 Promise 對象到底是個什麼東西呢 ?
Promise 是異步編程的一種解決方案,比傳統的解決方案回調函數更合理和更強大。ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。查看 Promise
先來了解一下它的基本用法
//創建 promise 對象
var promise=new Promise(function(resolve,reject){
// ...some async code
// 根據異步的結果來決定調用 resolve 或者 reject
})
//成功與失敗回調
promise.then(function(res){
//success
},function(error){
// error
});
在分析之前,我們先得知道,promise 的工作原理
Promise的三種狀態,注意Promise在某一時刻只能處於一種狀態
pending:進行中
fulfilled :執行成功
rejected :執行失敗
Promise的狀態改變,狀態只能由pending
轉換爲resolved
或者rejected
,一旦狀態改變完成後將無法改變(不可逆性)
pending------》fulfilled(resolved)
pending------》rejected
好了,瞭解完它的工作原理之後,我們再來分析代碼:在異步操作完成之後,會針對不同的返回結果調用resolve 和 reject 。
resolve和reject是兩個函數,
resolve是異步操作成功時候被調用,將異步操作的返回值作爲參數傳遞到外部;
reject是異步操作出異常時候被調用,將錯誤信息作爲參數傳遞出去。
異步結果傳遞出去後,使用then方法來獲取異步返回的結果,也就是上邊看到的 promise.then(...)
,怎麼樣,小夥伴們清楚了嘛 ? 簡單點來說就是:
1,定義一個 promise 對象,在裏邊做異步操作,並拿到返回結果
2,根據返回結果調用 resolve 或者 reject,來進行異步回調
3,執行對應的回調
當然了,相信很多童鞋門都在各種博客,論壇上看到了,promise 處理回調地獄這件事兒 , 其實原理也是很簡單的,就是成功回調的鏈式調用,,簡單的一個例子看一下吧。
var promise=new Promise(function(resolve,reject){
resolve(1)
})
promise.then(res => {
return res;
}).then(res =>
console.log(++res)
)
// 2
結果顯而易見了,需要 return
上一次的成功回調,接着鏈式調用 then
一直使用。
class
說到 class
是ES6 新增了類的說法,Class 可以通過extends關鍵字實現繼承,這比 ES5 的通過修改原型鏈實現繼承,要清晰和方便很多。
來認識一下class 類
// 類
class parent{
}
//child 繼承 parent , 也就是 子類繼承父類, 可以直接控制檯實踐的
class child extends parent{
}
typeof parent
// "function"
這裏可以看出來,typeof parent // "function"
parent 還是一個函數,其實 class parent {}
就是 ES2015 function parent () {}
的簡寫
我們再擴展一下
// 類
class parent{
constructor(x, y) {
this.x = 1;
this.y = 2;
}
}
//child 繼承 parent , 也就是 子類繼承父類, 可以直接控制檯實踐的
class child extends parent{
constructor(x, y, z) {
super(x, y); // 調用父類的 constructor(x, y)
this.z= 3;
}
}
那麼看到上邊的 constructor(x,y)
應該就不難理解了,就是 function parent (x,y) { this.x=x;this.y=y;}
寫過 react 項目的小夥伴應該很熟悉這段代碼。
super()
super代表父類的構造函數。ES6 要求,子類的構造函數必須執行一次super函數。
module
在這裏簡單介紹一下,後期我會專門寫一篇關於模塊兒化的文章
CommonJS: 用於Node.js環境
// 導出
module.exports = moduleA.func;
// 導入
const moduleA = require( url );
AMD: 用於Node.js環境,瀏覽器。異步方式家在模塊 -> requirejs
// 定義模塊
define( 'module', ['dep'], function(dep) {
return exports;
} )
// 導入模塊
require( ['module'], function(module) {} )
ES6模塊化: 需要轉化成es5運行
// 導出
export function hello(){};
export default {};
// 導入
import { A } from url;
import B from url;