国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

ES6新特性:使用export和import實現模塊化詳解

2019-11-19 15:56:26
字體:
來源:轉載
供稿:網友

在ES6前, 前端就使用RequireJS或者seaJS實現模塊化, requireJS是基于AMD規范的模塊化庫,  而像seaJS是基于CMD規范的模塊化庫,  兩者都是為了為了推廣前端模塊化的工具, 更多有關AMD和CMD的區別, 后面參考給了幾個鏈接;

現在ES6自帶了模塊化, 也是JS第一次支持module, 在很久以后 ,我們可以直接作用import和export在瀏覽器中導入和導出各個模塊了, 一個js文件代表一個js模塊;

現代瀏覽器對模塊(module)支持程度不同, 目前都是使用babelJS, 或者Traceur把ES6代碼轉化為兼容ES5版本的js代碼;

ES6的模塊化的基本規則或特點:

ES6的模塊化的基本規則或特點, 歡迎補充:

1:每一個模塊只加載一次, 每一個JS只執行一次, 如果下次再去加載同目錄下同文件,直接從內存中讀取。 一個模塊就是一個單例,或者說就是一個對象;

2:每一個模塊內聲明的變量都是局部變量, 不會污染全局作用域;

3:模塊內部的變量或者函數可以通過export導出;

4:一個模塊可以導入別的模塊

運行下面代碼

//lib.js//導出常量export const sqrt = Math.sqrt;//導出函數export function square(x) {  return x * x;}//導出函數export function diag(x, y) {  return sqrt(square(x) + square(y));}//main.jsimport { square, diag } from './lib';console.log(square(11)); // 121console.log(diag(4, 3)); // 5

下面列出幾種import和export的基本語法:

第一種導出的方式:

在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.jsexport default "string";//main.jsimport defaultString from "./lib";console.log(defaultString);

第五種導出方式:

export也能默認導出函數, 在import的時候, 名字隨便寫, 因為每一個模塊的默認接口就一個:

運行下面代碼

//lib.jslet fn = () => "string";export {fn as default};//main.jsimport defaultFn from "./lib";console.log(defaultFn());

第六種導出方式:

使用通配符*  ,重新導出其他模塊的接口 (其實就是轉載文章, 然后不注明出處啦);

運行下面代碼

//lib.jsexport * from "./other";//如果只想導出部分接口, 只要把接口名字列出來//export {foo,fnFoo} from "./other";//other.jsexport let foo = "stringFoo", fnFoo = function() {console.log("fnFoo")};//main.jsimport {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.jsexport let counter = 3;export function incCounter() {  counter++;}export function setCounter(value) {  counter = value;}//main.jsimport { counter, incCounter ,setCounter} from './lib';// The imported value `counter` is liveconsole.log(counter); // 3incCounter();console.log(counter); // 4setCounter(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="http://cdn.bootcss.com/require.js/2.2.0/require.min.js"></script><script>//cyclic.jsrequire(["file0"], function(file0) {  console.log(file0)})//file0.jsdefine(["file1"], function(file1) {  console.log(file1)  return {    file0 : "file0"  }})//file1.jsdefine(["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.jsimport fn0 from "./file0";fn0();//file0.jsimport fn1 from "./file1";fn1();console.log("file0.js runs");export default function() {console.log("file0 export runs")}//file1.jsimport fn0 from "./file0";fn0();console.log("file1.js runs");export default function() {console.log("file1 export runs")}

如果導出的是字符串:

運行下面代碼

//cyclic.jsimport str from "./file0";console.log(str);//file0.jsimport str1 from "./file1";console.log(str1)console.log("file0.js runs");export default "str0";//file1.jsimport 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會把不同類型的對象靜態解析成不同的初始值;

瀏覽器兼容:

  1. chrome瀏覽器目前不支持import,和export;
  2. 火狐的支持也有限, 比chrome好;
  3. 我都用babel;

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 金川县| 桓台县| 贵溪市| 天等县| 房产| 亳州市| 阜康市| 武山县| 阿拉善右旗| 额济纳旗| 满洲里市| 平远县| 吴忠市| 普安县| 阳城县| 黔西| 林周县| 江永县| 罗山县| 安平县| 县级市| 三门峡市| 浦东新区| 白朗县| 嘉兴市| 荣昌县| 邢台市| 南丰县| 山丹县| 苏尼特左旗| 西宁市| 咸宁市| 左贡县| 福泉市| 大姚县| 苍梧县| 松阳县| 清水县| 太湖县| 自贡市| 高雄市|