第一種導出的方式:
在lib.js文件中, 使用 export{接口} 導出接口, 大括號中的接口名字為上面定義的變量, import和export是對應的;
運行下面代碼
//lib.js 文件
let bar = "stringBar";
let foo = "stringFoo";
let fn0 = function() {
console.log("fn0");
};
let fn1 = function() {
console.log("fn1");
};
export{ bar , foo, fn0, fn1}
//main.js文件
import {bar,foo, fn0, fn1} from "./lib";
console.log(bar+"_"+foo);
fn0();
fn1();

第二種導出的方式:
在export接口的時候, 我們可以使用 XX as YY, 把導出的接口名字改了, 比如: closureFn as sayingFn, 把這些接口名字改成不看文檔就知道干什么的:
運行下面代碼
//lib.js文件
let fn0 = function() {
console.log("fn0");
};
let obj0 = {}
export { fn0 as foo, obj0 as bar};
//main.js文件
import {foo, bar} from "./lib";
foo();
console.log(bar);

第三種導出的方式:
這種方式是直接在export的地方定義導出的函數,或者變量:
運行下面代碼
//lib.js文件
export let foo = ()=> {console.log("fnFoo") ;return "foo"},bar = "stringBar";
//main.js文件
import {foo, bar} from "./lib";
console.log(foo());
console.log(bar);

第四種導出的方式:
這種導出的方式不需要知道變量的名字, 相當於是匿名的, 直接把開發的接口給export;
如果一個js模塊文件就只有一個功能, 那么就可以使用export default導出;
運行下面代碼
//lib.js export default "string"; //main.js import defaultString from "./lib"; console.log(defaultString);

第五種導出方式:
export也能默認導出函數, 在import的時候, 名字隨便寫, 因為每一個模塊的默認接口就一個:
運行下面代碼
//lib.js
let fn = () => "string";
export {fn as default};
//main.js
import defaultFn from "./lib";
console.log(defaultFn());
第六種導出方式:
使用通配符* ,重新導出其他模塊的接口 (其實就是轉載文章, 然后不注明出處啦);
運行下面代碼
//lib.js
export * from "./other";
//如果只想導出部分接口, 只要把接口名字列出來
//export {foo,fnFoo} from "./other";
//other.js
export let foo = "stringFoo", fnFoo = function() {console.log("fnFoo")};
//main.js
import {foo, fnFoo} from "./lib";
console.log(foo);
console.log(fnFoo());

其他:ES6的import和export提供相當多導入以及導出的語法;
在import的時候可以使用通配符*導入外部的模塊:
運行下面代碼
import * as obj from "./lib"; console.log(obj);
ES6導入的模塊都是屬於引用:
每一個導入的js模塊都是活的, 每一次訪問該模塊的變量或者函數都是最新的, 這個是原生ES6模塊 與AMD和CMD的區別之一,以下代碼修改自http://exploringjs.com/es6/ch_modules.html#_imports-are-read-only-views-on-exports
運行下面代碼
//lib.js
export let counter = 3;
export function incCounter() {
counter++;
}
export function setCounter(value) {
counter = value;
}
//main.js
import { counter, incCounter ,setCounter} from './lib';
// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
setCounter(0);
console.log(counter); // 0
在main.js中, counter一直指向lib.js中的局部變量counter, 按照JS的尿性, 像數字或者字符串類型或者布爾值的原始值要被復制, 而不是賦址;
循環依賴的問題:
NodeJS的循環依賴是這么處理的:打開;
循環依賴是JS模塊化帶來的問題, 在瀏覽器端, 使用RequireJS測試模塊化, 比如有一個文件file0.js依賴於file1.js, 而file1.js又依賴於file0.js, 那么file0.js和file1.js到底誰先執行?
運行下面代碼
//index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
</head>
<body>
<script data-main="cyclic" src="//cdn.bootcss.com/require.js/2.2.0/require.min.js"></script>
<script>
//cyclic.js
require(["file0"], function(file0) {
console.log(file0)
})
//file0.js
define(["file1"], function(file1) {
console.log(file1)
return {
file0 : "file0"
}
})
//file1.js
define(["file0"], function(file0) {
console.log(file0);
return {
file1 : "file1"
}
})
</script>
</body>
</html>
在控制台的依次輸出為:
運行下面代碼
undefined
Object { file1: "file1" }
Object { file0: "file0" }
在執行file1.js的時候file0.js還沒執行完, 所以輸出了undefined, 這種輸出結果和NodeJS輸出的情況是一樣的;
然后我又使用了司徒大神的mass-framework框架試了一下, 司徒大神的框架直接提示我: "模塊與之前的某些模塊存在循環依賴", 這樣還比較好點, requireJS對於循環依賴是直接執行循環依賴的模塊, 會導致在開發的時候給自己挖坑....;
接下來我又在babel-node下進行測試:下面是幾個測試,可以無視:
我使用ES6的模塊試一試, 只要每一個模塊被引用, 無論模塊是否執行完畢, 該模塊的export已經被導出了, 如果導出的是函數:
運行下面代碼
//cyclic.js
import fn0 from "./file0";
fn0();
//file0.js
import fn1 from "./file1";
fn1();
console.log("file0.js runs");
export default function() {console.log("file0 export runs")}
//file1.js
import fn0 from "./file0";
fn0();
console.log("file1.js runs");
export default function() {console.log("file1 export runs")}

如果導出的是字符串:
運行下面代碼
//cyclic.js
import str from "./file0";
console.log(str);
//file0.js
import str1 from "./file1";
console.log(str1)
console.log("file0.js runs");
export default "str0";
//file1.js
import str0 from "./file0";
console.log(str0)
console.log("file1.js runs");
export default "str1";

如果導出的是對象:
那么第一行會先輸出一個初始值{},在最后等待file0.js和file1.js執行完畢以后, 才輸出file0.js導出的對象;
如果是數組:
那么第一行會輸出一個被靜態分析過的初始值undefined,在最后等待file0.js和file1.js執行完畢以后, 才輸出file0.js導出的對象;
如果是布爾值:
那么第一行會輸出一個被靜態分析過的初始值undefined,在最后等待file0.js和file1.js執行完畢以后, 才輸出file0.js導出的布爾值;
為什么會這樣呢? 我好像在這邊找到了答案:http://exploringjs.com/es6/ch_modules.html#_modules ,ES6的import和export被提前到js的最頂層, 在函數或者對象,或者基本值被導出去的時候提前被靜態分析過,參考:http://www.ecma-international.org/ecma-262/6.0/#sec-parsemodule , http://www.ecma-international.org/ecma-262/6.0/#sec-toplevelmoduleevaluationjob
結論:用ES6的export導出數據接口的時候, 最好統一用函數, 避免在循環依賴的時候, 因為JS會把不同類型的對象靜態解析成不同的初始值;

