前端模塊化的好處都已經被說爛了,概括爲兩點:html
ES2015終於引入了模塊的概念,最近學習了下,順便記下筆記。前端
index.html
<!DOCTYPE html> <html> <head></head> <body> <h1>import</h1> <script src="index.js" type="module"></script> </body> </html>
index.js
export
export
語句導出該模塊輸出的變量;export
語句有兩種語法格式:命名導出, 默認導出。命名導出就是明確導出的變量名稱和值。git
在目錄下建立math.js,內容以下:github
// Case 1: export後面跟變量輸出聲明語句 export var PI = 3.14; // Case 2: export後面直接跟變量定義語句 export var add = function (x, y) { // 導出函數print return x + y; }
這表示math.js模塊導出變量PI
和add
。用NodeJS的模塊格式可表示爲:瀏覽器
var PI = 3.14; var add = function (x, y) { // 導出函數print return x + y; } module.exports.PI = PI; module.exports.add = add;
index.js內容:模塊化
import * as Math from "./math.js"; // import是導入模塊,後面會說。 console.log(Math.PI); console.log(Math.add(1, 2));
用瀏覽器打開頁面,看看輸出結果是否OK:函數
3.14
3
// 調整math.js內容 var PI = 3.14; var add = function (x, y) { return x + y; } export { PI, add }; // 簡寫格式,統一列出須要輸出的變量
簡寫格式還能夠對輸出的變量重命名:學習
// 再次修改math.js var PI = 3.14; var add = function (x, y) { return x + y; } export { PI, add as Add}; // 把輸出變量add重命名爲Add(注意不用雙引號)
經過關鍵字as
把輸出變量add
重命名爲Add
(Add是個字面量,不是字符串不須要引號)。prototype
一樣在index.js模塊也要修改下:code
import * as Math from "./math.js"; console.log(Math.PI); console.log(Math.Add(1, 2)); // Add方法名稱改動了。
export
語句後面能夠跟什麼?命名導出須要同時指定導出的變量名稱和變量值,因此export
語句後面跟的通常是:
export
簡寫格式。不能夠是表達式,由於表達式只有值,沒有名字。
// 語法錯誤:Declaration or statement expected export 3.14
經過關鍵字default
修飾export
能夠指定一個模塊的默認輸出變量值(在導入模塊的默認輸出時,不須要指定導出變量名稱,這個後面再說)。
// Case 3 常量 export default 25; // Case 4 變量 var PI = 3.14; export default PI // Case 5 函數 export default function add2( x, y) { return x + y; }
default
的模塊輸出變量;export default 3.14
export
命名導出;export default
默認導出;export
語句必須在模塊做用域的最頂層,即export
不能夠出如今任意花括號內,如函數語句裏,子代碼塊裏(控制語句)。經過import
語句導入外部模塊。對應export
語句的兩種導出方式,import
也分別存在兩種不一樣的模塊導入語法格式。
修改index.js:
import { PI, Add } from './math.js'; console.log(PI); console.log(Add(1, 2));
表示:導入math.js模塊裏輸出的變量PI
, Add
。
注意名稱必需要和math.js模塊的輸出變量一一對應,不然就是undefined
。
該格式還支持對導入的變量重命名:
import { PI as pi, Add as add} from './math.js';
*
若是導入一個模塊全部命名輸出,可採用通配符*
。
// 修改index.js import * as Math from './math.js'; // 此時必須經過as指定個別名 console.log(Math.PI); console.log(Math.Add(1, 2));
表示導入模塊math.js全部命名輸出變量,並經過Math
變量訪問全部命名導出的變量。Math
變量是個特殊的對象,叫模塊對象。
Object.prototype.toString.call(Math); // [object Module]
而且這個對象和它的屬性都是隻讀的(後面細說)。
// 修改math.js: var PI = 3.14; var add = function (x, y) { return x + y; } export { PI, add as Add }; // 簡寫格式,統一列出須要輸出的變量 export default function say() { // 默認輸出 console.log("I am default export"); }
修改index.js:
import say from "./math.js"; say();
as
重命名;導入模塊默認輸出的名字能夠任意命名。
import say2 from "./math.js"; // say2();
import say, * as Math from './math.js'; // OR import say, { PI, Add } from './math.js';
默認導入必定放在命名導入前面
// 非法 import * as Math, say from './math.js'; // 非法 import { PI, Add }, say from './math.js';
若是隻導入一個模塊,但不引用模塊的輸出變量,能夠簡寫爲:
import './math.js'
此時只會觸發模塊math.js的執行。
import xx from "xxx"
導入默認輸出;import { xx } from "xxx"
導入指定的命名輸出;import * as xx from "xxx"
導入所有命名輸出;import "xxx"
只導入;import
語句也必須在模塊的最頂層做用域裏,即import不能夠出如今任意花括號內,如函數語句裏,子代碼塊裏(控制語句)。模塊能夠導出任何類型變量(引用變量和值變量),若是在模塊index.js裏修改了模塊math.js導出的引用變量或者值變量,那會影響模塊math.js裏的值麼?
很遺憾,import
導入的變量和變量的屬性都是隻讀的,不能也不該該修改引入的變量值。
import * as Math from './math.js'; // TypeError: Cannot assign to read only property 'Count' of object '[object Module]' Math.Count = 12;
反過來想一想,若是模塊math.js修改了其導出的引用變量或者值變量在,那會影響模塊index.js裏的取值麼?
修改math.js:
var Count = 0; var increase = function() { Count++; } var Person = { name: 'Bob' } var changeName = function() { Person.name = 'John'; } export { Count, Person, increase, changeName };
修改index.js:
import * as Math from './math.js'; console.log(`Person:${JSON.stringify(Math.Person)}, Count:${Math.Count}`);// 修改前 Math.increase(); Math.changeName(); console.log(`Person:${JSON.stringify(Math.Person)}, Count:${Math.Count}`);// 修改後
輸出:
Person:{"name":"Bob"}, Count:0
Person:{"name":"John"}, Count:1
從輸出能夠看出只要math.js修改了導出值就會影響index.js的取值。
The static import statement is used to import read only live bindings which are exported by another module
export
語句瞭解了export
和import
基本用法後,咱們再看看export
語句另外一個語法規則:導出引入的模塊的變量。
上面的例子裏export
語句都是導出模塊自身定義的變量,其實export
還能夠導出模塊引入模塊的輸出。
在目錄添加文件log.js:
export var Log = function(msg) { console.log(msg); } export default 'I am log.js';
修改math.js:
var Count = 0; var increase = function() { Count++; } var Person = { name: 'Bob' } var changeName = function() { Person.name = 'John'; } export { Count, Person, increase, changeName}; export default function say() { console.log(`Person:${JSON.stringify(Person)}, Count:${Count}`) } export * from './log.js'; //
修改index.js:
import say, * as Math from './math.js'; Math.Log('hello'); // 該方法來之log.js模塊
查看下輸出是否OK。
其中export * from './log.js';
表示導出模塊log.js全部的命名輸出。等價於:
export { Log } from './log.js';
注意: 這種語法格式export * from './log.js';
不能夠定義別名,而花括號的語法格式export { Log } from './log.js'
能夠定義別名,即:
export { Log as log} from './log.js'
怎麼在math.js模塊裏導出模塊log.js的默認輸出呢?
只能採用先導入,再導出方式:
import logName from './log.js'; export { logName }
整理自gitHub筆記ES2015模塊 & import, export