ES6之module

来源:http://www.cnblogs.com/giggle/archive/2016/06/14/5572118.html
-Advertisement-
Play Games

JavaScript一直沒有模塊體系,但是伴隨著ES6的到來,module隨之而來。ES6module提倡一個js文件就是一個模塊的概念,主要包括兩個命令:export和import,用於模塊向外提供介面(export)和引入其他模塊介面(import)。該隨筆分為四部分:1、ES6module概述... ...


一、module概述

JavaScript一直沒有模塊體系,但是伴隨著ES6的到來,module隨之而來。

ES6module的設計思想是儘量的靜態化,使得編譯時就能確定模塊的依賴關係,以及輸入、輸出變數。簡而言之就是‘編譯時載入’。

ES6module相對來說實現得還是比較簡單,易上手。

ES6module提倡一個js文件就是一個模塊的概念,主要包括兩個命令:export和import,用於模塊向外提供介面(export)和引入其他模塊介面(import)。

好了,下麵就說下我說理解的export命令和import命令。

註:學習ES6之module需要有個轉換器,因為現在好多還沒有支持ES6的module。見“ES6轉換ES5

二、export命令

export命令說白了就是用於模塊對外提供的介面。

語法如下:

var f = 1;
export {f};

或者

export var f = 1;

但是不能是下麵這個樣子:

var f = 1;
export f;

為什麼呢?

需要註意ES6module是向外拋的值的引用,是引用(這和CommonJS模塊不一樣,CommonJS是向外拋的值的拷貝)

所以,你像上面這樣肯定不對嘛,因為export f就是向外拋的值了,不是引用咯。

並且,還需要註意的是,export不是最後處理的哦,什麼意思?

比如test1:

export {name};
var name = 'Monkey';

如上,這樣其實向外拋的是空,如果用ES6module的import(import在下麵會詳情說到)引用它,會輸出undefined。

如下(利用import)test2:

import {name} from './test';
console.log(name);

將test1和test2,利用babel轉換成ES5後的代碼如下:

test1:

test2:

在node環境下運行test2,得下:

所以,export在ES6module中,和代碼一樣依行執行。而不像ES6module中的import那樣會將其提升到模塊頂部,首先執行。

三、import命令

import命令說白了,就是引用export對外提供的介面。對,是引用,而不是賦值。

import的用法如下:

/*
    name為test.js文件中export往外拋的引用名,名字必須一一對應
    from後面的'./test'為你所引入模塊的相對路徑
*/
import {name} from './test';

其中,如果你想改變引用名,可以用as,如下:

import {name as ourName} from './test';

如果你想引入模塊中的所有變數,可以利用通配符*,然後利用as自定義名稱,如下:

//引入test模塊的所有拋出的引用,並將其存放在allVar中
import * as allVar from './test';
//隨後,如果test模塊中有one方法,我們可以這麼使用
allVar.one();

像上面這些例子中,我們用import都需要明確指定模塊中對應的引用名稱,或者使用*全部引用。其實,我們還可以在export中設置default,這樣import引用模塊時,就不需要指定使用名啦。

什麼意思?

如下:

//test模塊
function getName(){
    console.log('Monkey');
};
//default其實就相當於ES6module為我們設定的一個名字,對應getName的值
export default getName;

//使用test模塊,one是我隨便起的名字,它就對應default,而不需要{}了
import one from './test';
四、升華

ES6module輸出的值是值的引用。我們可以通過一個demo,更透徹地認識這點。

如下:

//模塊sample
var i = 0;
export {i};
//模塊test1,引入sample模塊
import {i} from './sample';
i++;
//模塊test2,引入sample模塊
import {i} from './sample';
console.log(i);
//模塊main,引入test1和test2模塊
import './test1';
import './test2';

利用bable轉換:

報錯了!!在模塊test1中的i++是只讀的。(’i’ is read-only).

原因就是:由於ES6輸入的模塊變數,只是一個”符號連接“,所以這個變數是只讀的,對它進行重新賦值會報錯。(摘自‘阮一峰—ECMAScript6入門’)。

我們再修改下上面的代碼,

如下:

利用bable轉換如上代碼後,利用cmd,運行main.js,得如下結果:

 

我們在main.js中是利用import引入test1和test2模塊,但是,從上面的結果可以看出,他們是引用的同一份sample。

所以,ES6module輸出的值是值的引用。且,因為ES6module輸出的值是值的引用。所以當出現迴圈引用模塊時,它和CommonJS是不一樣的。

如下,CommonJS’s Demo:

註:CommonJS是值的拷貝,不是引用。

main.js

var y = require('./test');
exports.b = 'dorie';
setTimeout(function(){
    console.log(y.y);
},2000); 

test.js

var b = require('./main');
var y;
setTimeout(function(){
    y = 'monkey' + b.b;
},1000);  
exports.y = y;  

運行main.js,得下結果:

 

Why?

因為CommonJS是值的拷貝,當執行main.js時,引入test模塊,將y的值賦值給main.js里的y變數,此時y是undefined,且已經賦值了,但test模塊在1秒後運行setTimeout里的匿名函數後,y變為’monkey’ + b.b,可是對main.js里的y已經無影響,因為是值拷貝嘛。

我們將上述代碼換成ES6module的形式,如下:

main.js

import {y} from './test';
export var b = 'dorie';
setTimeout(function(){
    console.log(y);
},2000);  

test.js

import {b} from './main';
var y;
setTimeout(function(){
    y = 'monkey' + b;
},1000);  
export {y}; 

利用Bable將ES6module轉換成ES5後,在node環境下運行轉換後的main.js,得如下結果:

 

其實邏輯與上述CommonJS是一樣的,但是結果卻不一樣,原因就是ES6module是值的引用!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.先奉上整理的14圖。 2.其次奉上整理的圖之間的6種關係 ...
  • 函數調用方法 在談論JavaScript中apply、call和bind這三兄弟之前,我想先說下,函數的調用方式有哪些: 作為函數 作為方法 作為構造函數 通過它們的call()和apply()方法間接調用 前面的三種調用方法,我們都知道且不在這篇文章的討論範圍內,就不說了。 下麵我們來說說這第四種 ...
  • 1、塊級元素 一般用來搭建網站架構、佈局、承載內容……它包括以下這些標簽: address、blockquote、center、dir、div、dl、dt、dd、fieldset、form、h1~h6、hr、isindex、menu、noframes、noscript、ol、p、pre、table、 ...
  • 目前主流瀏覽器的相容性做的都比較好了,本文主要針對IE6,7的不相容問題進行解決。 1.有浮動存在時,計算一定要精確,不要讓內容的寬高超出我們所設置的寬高,IE6下,內容會撐開設置好的高度。 解決方法:給對應的父級加overflow:hidden;但是會有部分被隱藏掉,最好是精確計算寬高再設定 eg ...
  • 前言: 1.HTML5的發展非常迅速,可以說已經是前端開發人員的標配,在電商類型的APP中更是運用廣泛,這個系列的文章是本人自己整理,儘量將開發中不常用到的剔除,將經常使用的拿出來,使需要的朋友能夠真正快速入門,如果有哪些不清楚的地方或者錯誤,歡迎聯繫我 2.更新時間沒有規律,一般會在3天左右更新一 ...
  • 一丶 流 什麼是流? 比如 react 中的單項數據流,Node.js 中的流,或者本文中的 DOM 事件流,都是流的具體體現。專業地講,流是程式輸入或輸出的一個連續的位元組序列;通俗地講,流是有方向的數據。 二丶 事件流 什麼是事件流? 假想一下,現在有一組同心圓,你把手指在最裡面的圓心上,與此同時 ...
  • 1:視頻播放器2:地理定位 我們的支持html5 的瀏覽器給我們提供一個介面(api),可以用來獲取你當前的位置. 主要是通過geolocation(地理位置),對象 ,去訪問硬體,來獲取到經緯度.. 我們獲取到的是一個經緯度。我們調用地圖。我們調用百度地圖.(街景地圖) 3: 拖拽 html5 里 ...
  • 1.prototype和__proto__ 所有對象的__proto__都指向其構造器的prototype,即constructor的原型 2.變數作用域的問題 通常認為在當前作用域中找不到變數值時會到其父作用域中去尋找,這種說法是不准確的,應該是會到創建這個函數的作用域中去找 3.settimeo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...