node裡面的模組 和 es6裡面的模組引入方式
出處:https://blog.csdn.net/arsaycode/article/details/78959780
node: module.exports和require
es6:export和import
node:
該模組實現方案主要包含 require 與 module 這兩個關鍵字,其允許某個模組對外暴露部分介面並且由其他模組匯入使用。
//sayModule.js
function SayModule () {
this.hello = function () {
console.log('hello');
};
this.goodbye = function () {
console.log('goodbye');
};
}
module.exports = SayModule;
//main.js 引入sayModule.js
var Say = require('./sayModule.js');
var sayer = new Say();
sayer.hello(); //hello
作為一個伺服器端的解決方案,CommonJS 需要一個相容的指令碼載入器作為前提條件。該指令碼載入器必須支援名為 require 和 module.exports 的函式,它們將模組相互匯入匯出。
ES6模組(module)
模組Module
一個模組,就是一個對其他模組暴露自己的屬性或者方法的檔案。
匯出Export
作為一個模組,它可以選擇性地給其他模組暴露(提供)自己的屬性和方法,供其他模組使用。
// profile.js
export var firstName = 'qiqi';
export var lastName = 'haobenben';
export var year = 1992;
//等價於
var firstName = 'qiqi';
var lastName = 'haobenben';
var year = 1992;
export {firstName, lastName, year}
1、 通常情況下,export輸出的變數就是本來的名字,但是可以使用as關鍵字重新命名。
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
//上面程式碼使用as關鍵字,重新命名了函式v1和v2的對外介面。重新命名後,v2可以用不同的名字輸出兩次。
2、 需要特別注意的是,export命令規定的是對外的介面,必須與模組內部的變數建立一一對應關係。
// 報錯
export 1;
// 報錯
var m = 1;
export m;
//上面兩種寫法都會報錯,因為沒有提供對外的介面。第一種寫法直接輸出1,第二種寫法通過變數m,還是直接輸出1。1只是一個值,不是介面。
/ 寫法一
export var m = 1;
// 寫法二
var m = 1;
export {m};
// 寫法三
var n = 1;
export {n as m};
//上面三種寫法都是正確的,規定了對外的介面m。其他指令碼可以通過這個介面,取到值1。它們的實質是,在介面名與模組內部變數之間,建立了一一對應的關係。
匯入import
作為一個模組,可以根據需要,引入其他模組的提供的屬性或者方法,供自己模組使用。
1、 import命令接受一對大括號,裡面指定要從其他模組匯入的變數名。大括號裡面的變數名,必須與被匯入模組(profile.js)對外介面的名稱相同。如果想為輸入的變數重新取一個名字,import命令要使用as關鍵字,將輸入的變數重新命名。
import { lastName as surename } from './profile';
2、import後面的from指定模組檔案的位置,可以是相對路徑,也可以是絕對路徑,.js路徑可以省略。如果只是模組名,不帶有路徑,那麼必須有配置檔案,告訴 JavaScript 引擎該模組的位置。
3、注意,import命令具有提升效果,會提升到整個模組的頭部,首先執行。
foo();
import { foo } from 'my_module';
//上面的程式碼不會報錯,因為import的執行早於foo的呼叫。這種行為的本質是,import命令是編譯階段執行的,在程式碼執行之前。
4、由於import是靜態執行,所以不能使用表示式和變數,這些只有在執行時才能得到結果的語法結構。
/ 報錯
import { 'f' + 'oo' } from 'my_module';
// 報錯
let module = 'my_module';
import { foo } from module;
// 報錯
if (x === 1) {
import { foo } from 'module1';
} else {
import { foo } from 'module2';
}
5、最後,import語句會執行所載入的模組,因此可以有下面的寫法。
import 'lodash';
//上面程式碼僅僅執行lodash模組,但是不輸入任何值。
預設匯出(export default)
每個模組支援我們匯出一個
沒有名字的變數,使用關鍵語句export default來實現.
export default function(){
console.log("I am default Fn");
}
//使用export default關鍵字對外匯出一個匿名函式,匯入這個模組的時候,可以為這個匿名函式取任意的名字
//取任意名字均可
import sayDefault from "./module-B.js";
sayDefault();
//結果:I am default Fn
1、預設輸出和正常輸出的比較
// 第一組
export default function diff() { // 輸出
// ...
}
import diff from 'diff'; // 輸入
// 第二組
export function diff() { // 輸出
// ...
};
import {diff} from 'diff'; // 輸入
//上面程式碼的兩組寫法,第一組是使用export default時,對應的import語句不需要使用大括號;第二組是不使用export default時,對應的import語句需要使用大括號。
export default命令用於指定模組的預設輸出。顯然,一個模組只能有一個預設輸出,因此export default命令只能使用一次。所以,import命令後面才不用加大括號,因為只可能對應一個方法。
2、因為export default本質是將該命令後面的值,賦給default變數以後再預設,所以直接將一個值寫在export default之後。
/ 正確
export default 42;
// 報錯
export 42;
//上面程式碼中,後一句報錯是因為沒有指定對外的介面,而前一句指定外對介面為default。
3、如果想在一條import語句中,同時輸入預設方法和其他變數,可以寫成下面這樣。
import _, { each } from 'lodash';
//對應上面程式碼的export語句如下
export default function (){
//...
}
export function each (obj, iterator, context){
//...
}
export 與 import 的複合寫法
如果在一個模組之中,先輸入後輸出同一個模組,import語句可以與export語句寫在一起。
export { foo, bar } from 'my_module';
// 等同於
import { foo, bar } from 'my_module';
export { foo, bar };
/ 介面改名
export { foo as myFoo } from 'my_module';
// 整體輸出
export * from 'my_module';
注意事項
1、宣告的變數,對外都是隻讀的。但是匯出的是物件型別的值,就可修改。
2、匯入不存在的變數,值為undefined。
ES6 中的迴圈引用
ES6 中,imports 是 exprts 的只讀檢視,直白一點就是,imports 都指向 exports 原本的資料,比如:
//------ lib.js ------
export let counter = 3;
export function incCounter() {
counter++;
}
//------ main.js ------
import { counter, incCounter } from './lib';
// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
// The imported value can’t be changed
counter++; // TypeError
因此在 ES6 中處理迴圈引用特別簡單,看下面這段程式碼:
//------ a.js ------
import {bar} from 'b'; // (1)
export function foo() {
bar(); // (2)
}
//------ b.js ------
import {foo} from 'a'; // (3)
export function bar() {
if (Math.random()) {
foo(); // (4)
}
}
假設先載入模組 a,在模組 a 載入完成之後,bar 間接性地指向的是模組 b 中的 bar。無論是載入完成的 imports 還是未完成的 imports,imports 和 exports 之間都有一個間接的聯絡,所以總是可以正常工作。
例項
//---module-B.js檔案---
//匯出變數:name
export var name = "cfangxu";
moduleA模組程式碼:
//匯入 模組B的屬性 name
import { name } from "./module-B.js";
console.log(name)
//列印結果:cfangxu
批量匯出
//屬性name
var name = "cfangxu";
//屬性age
var age = 26;
//方法 say
var say = function(){
console.log("say hello");
}
//批量匯出
export {name,age,say}
批量匯入
//匯入 模組B的屬性
import { name,age,say } from "./module-B.js";
console.log(name)
//列印結果:cfangxu
console.log(age)
//列印結果:26
say()
//列印結果:say hello
重新命名匯入變數
import {name as myName} from './module-B.js';
console.log(myName) //cfangxu
整體匯入
/使用*實現整體匯入
import * as obj from "./module-B.js";
console.log(obj.name)
//結果:"cfangxu"
console.log(obj.age)
//結果:26
obj.say();
//結果:say hello