ES6之module


該博客原文地址:http://www.cnblogs.com/giggle/p/5572118.html

一、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是值的引用!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM