歷史上,JavaScript一直沒有模塊體系,沒法將一個大程序拆分紅相互依賴的小文件,再用簡單的方法拼裝起來。這對開發大型的、複雜的項目造成了巨大的障礙。react
在es6以前社區制定了一些模塊加載方案, 主要有 COmmonJS 和 AMD 兩種。前者用於服務器,後者用於瀏覽器。es6
CommonJS 和 AMD 模塊 , 採用的是 「運行時加載」 , 是將暴露的變量、方法等構成一個對象,而後再從這個而對象上讀取對應的方法。也就是說會將全部的方法都進行加載。瀏覽器
ES6模塊 ,採用的是 「編譯時加載」或者靜態加載。即只加載須要的方法,其餘的方法不加載。緩存
ES6能夠在編譯時就完成模塊加載,效率要比CommonJS高,固然,這也致使了無法引用 ES6 模塊自己,由於它不是對象。服務器
ES6 的模塊自動採用嚴格模式,無論你有沒有在模塊頭部加上 "use strict"函數
嚴格模式主要有如下限制 :this
模塊功能主要有兩個命令構成 : export 和 import 。 export命令用於規定模塊的對外接口,import命令用於輸入其餘模塊提供的功能。spa
一個模塊就是一個獨立的文件。該文件內部的全部變量,外部沒法獲取。若是你但願外部可以讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。code
export 命令輸出變量 :對象
// 1.
export const fristName = "buzhanhua";
//2.
const lastName = "Jone";
export {lastName}
複製代碼
兩種寫法是等價的,可是推薦第二種,因爲export規定的是對外接口因此第二種要使用 {} 而不能直接名稱
export 命令輸出變量或類(class)。
export function fn(){
console.log("zzz")
}
function fn(){
console.log("zzz")
}
export {fn}
複製代碼
一般狀況下 , export輸出的變量名稱就是之後引入時的名稱 , 可是可使用 as 關鍵字重命名。
function fn(){
console.log("zzz")
}
export {
fn as haha,
fn as zzzz
}
複製代碼
通過重命名後同一個方法能夠以不一樣的名稱屢次輸出。
export語句輸出的接口,與對應的值是動態綁定的,即經過該接口,能夠取到模塊內部實時的值。
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);
複製代碼
上面代碼 foo 在500 毫秒後變爲 ‘baz’ , 也就是500毫秒後再取則是baz.
這一點與CommonJS規範徹底不一樣。CommonJS模塊輸出的是值的緩存,不存在動態更新
export 命令能夠出如今模塊的任何位置,只要是模塊頂層就能夠。
function fn(){
console.log("zzz");
export {lastName}
}
// 報錯
複製代碼
使用export命令定義了模塊的對外接口之後,其餘 JS 文件就能夠經過import命令加載這個模塊。
import命令接受一對大括號,裏面指定要從其餘模塊導入的變量名。大括號裏面的變量名,必須與被導入模塊(profile.js)對外接口的名稱相同。
import {fristName,lastName,haha} from './profile';
複製代碼
import 命令可使用 as 關鍵字,將輸入的變量重命名。
import {fristName as bigName} from './profile';
複製代碼
import 後面的from 指定文件的位置 , 能夠是相對路徑, 也能夠是絕對路徑,.js 能夠省略。若是隻是模塊名,不帶有路徑,那麼必須有配置文件告訴JavaScript該模塊的位置。
import 命令具備提高效果,會提高到整個模塊的頭部,首先執行。
haha();
import {haha} from './profile';
複製代碼
上面代碼不會報錯, 本質是由於, import命令是編譯階段執行的, 在代碼運行前。
因爲 import 是靜態執行的, 因此不能使用表達式和變量 ,這些只有在運行時才能獲得結果的語法結構。
import {'ha'+'ha'} from './profile';
let a = 'haha';
import {a} from './profile';
// if 語句 function 都會報錯
複製代碼
import 語句能夠執行所加載的模塊 , 但不會輸出任何值。
import './profile';
複製代碼
若是屢次重複執行同一句import語句,那麼只會執行一次,而不會執行屢次。
import { foo } from 'my_module';
import { bar } from 'my_module';
// 等同於
import { foo, bar } from 'my_module';
複製代碼
上面代碼中,雖然foo和bar在兩個語句中加載,可是它們對應的是同一個my_module實例。也就是說,import語句是 Singleton 模式。
除了指定輸出某個值,和能夠總體輸出 , 即便用 "*" 指定一個對象, 全部的輸出值都放到這個對象上。
// circle.js
export function sum(a,b){
console.log(a+b);
}
export function area(radius){
let area = Math.PI*radius*radius;
console.log(area);
}
export var a = 12;
//main.js
import * as haha from './circle';
haha.sum(1,2);
haha.area(4);
console.log(haha.a)
複製代碼
使用import命令的時候,用戶須要知道所要加載的變量名或函數名,不然沒法加載。爲了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default命令,爲模塊指定默認輸出。export default在一個模塊(文件)中只能使用一次,而export則可使用屢次。
export default function(){
console.log("我是默認")
}
複製代碼
其餘模塊加載該模塊時,import命令能夠爲該匿名函數指定任意名字。
import fn from './circle';
fn() // 我是默認
複製代碼
注意 : 這時import命令後面,不使用大括號。
export default命令用在非匿名函數前,也是能夠的。
//1.
export default function foo(){
console.log("我是默認")
}
//2.
function foo(){
console.log("我是默認")
}
export default foo
複製代碼
上面代碼中,foo函數的函數名foo,在模塊外部是無效的。加載的時候,視同匿名函數加載。
var a = 1;
export default a; // 正確
export default 1 ; // 正確
export default var a = 1 ; // 錯誤
複製代碼
由於export default命令其實只是輸出一個叫作default的變量,因此它後面不能跟變量聲明語句。上面代碼中,export default a的含義是將變量a的值賦給變量default。因此,最後一種寫法會報錯。
export default class love {
getLoverName(){
console.log('sun')
}
}
複製代碼
若是想在一條import語句中,同時輸入默認方法和其餘變量,能夠寫成下面這樣
import react , {Component} from 'react';
複製代碼
若是在一個模塊之中,先輸入,後輸出同一個模塊,import語句能夠與export語句寫在一塊兒
// profile.js
export {sum,area} from './circle';
//等同於
import {sum,area} from './circle';
export {sum,area};
//main.js
import {sum} from './profile';// 就可使用了
複製代碼
塊的接口更名 (as)
export {area as pipixia} from './circle'
複製代碼
總體輸出 (*)
export * from './circle';
複製代碼
獲取某個模塊的默認接口,並做爲本身的默認接口導出
export {default} from './circle'
複製代碼
具名接口改成本身的默認接口
export {sum as default} from './circle';
複製代碼
將引入的默認接口轉化爲本身的具名接口並輸出
export {default as hei} from './circle'
複製代碼
模塊之間也是能夠繼承的
export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
複製代碼
注意,export *命令會忽略circle模塊的default方法。而後,上面代碼又輸出了自定義的e變量和默認方法。
<script type="module" src="foo.js"></script>
複製代碼
「循環加載」(circular dependency)指的是,a腳本的執行依賴b腳本,而b腳本的執行又依賴a腳本。
1、export default
2、