require OR import
以前在CommonJS中,我們用module.exports和require來匯出和匯入模組,而到了ES6卻變成了export和import了,這兩者到底有什麼區別呢?
一句話總結:CommonJS模組是執行輸出(載入)一個值(或物件)的拷貝,而ES6模組則是編譯時輸出(載入)一個值的引用(或者叫做連線).
這樣的差異在平常使用是不易被察覺的,可是一旦出現迴圈引用,兩者的差異就很明顯了。直接的迴圈引用(a引用b,b又引用a)一般不會有,但在依賴關係複雜的大專案中,很容易出現a引用b,b引用其它模組,在若干次引用後,模組n又引用回a這樣的情況。為了講解的方便我們直接構造出一個a,b相互引用的專案。
首先,我們來看看CommonJS模組中的現象:
// APage.js 關鍵程式碼
let BPage = require('./BPage');
class APage extends Component {
render() {
return (
<View style={styles.containerAll} >
<TouchableOpacity style={styles.btn} onPress={this.onPress.bind(this)}>
<Text>PushToB</Text>
</TouchableOpacity>
</View>
);
}
onPress() {
this.props.navigator.push(BPage);
}
}
var route = {
key: 'APage',
component: APage,
};
module.exports = route;
// BPage.js 關鍵程式碼
let APage = require('./APage');
class BPage extends Component {
constructor(props) {
super(props);
console.log('BPage alloc');
}
render() {
return (
<View style={styles.containerAll} >
<TouchableOpacity style={styles.btn} onPress={this.onPress.bind(this)}>
<Text>resetToA</Text>
</TouchableOpacity>
</View>
);
}
onPress() {
this.props.navigator.resetTo(APage);
}
}
var route = {
key: 'BPage',
component: BPage,
};
module.exports = route;
可以看到,APage正常顯示,並且點選PushToB可以正常顯示出BPage,可從BPage再Reset到APage就成了空白了。這是為什麼呢?
我們來仔細分析一下整個過程:CommonJS的一個模組,就是一個指令碼檔案,require命令第一次載入該指令碼,就會執行整個指令碼,然後在記憶體生成一個物件。本例在index.js中先require了APage.js,那就開始執行該指令碼,可是在執行過程中先遇到了let BPage = require('./BPage');
這時候就會先去執行BPage.js。在BPage.js中又會遇到let APage = require('./APage');
但這時候APage.js
已經開始執行了,不會重複執行,所以系統會去模組對應的exports
屬性取值,可是因為APage.js
還沒執行完,從exports
屬性中只能取回已經執行的部分,所以APage
還是空的,也就是說resetTo(APage)
其實是reset到一個空。接著BPage.js
會繼續往下執行,等到全部執行完畢,再把執行權還給APage.js
。
從上面的例子可以看出,在複雜專案中載入CommonJS模組需要非常小心處理各模組之間的引用關係。接下來我們來看看同樣的場景在ES6中會是怎樣:
// APage.js 關鍵程式碼
import BPage from './BPage';
...//中間部分與上文相同,故不重複貼程式碼
export default route;
// BPage.js 關鍵程式碼
import APage from './APage';
...//中間部分與上文相同,故不重複貼程式碼
export default route;
只是把匯入和匯出改為import和export,這一次就可以順利走完整個流程,得到我們想要的。這是因為import只是指向被載入模組,我們只需要保證真正取值的時候能夠取到值即可。與require時相同,在APage.js
中遇到import BPage from './BPage';
也是會先去執行BPage.js
,也就是說BPage.js
在遇到import APage from './APage';
時,APage.js
同樣是沒執行完,這時候APage是undefined。不同的是使用import
從一個模組載入變數,那些變數不會被快取,而是成為一個指向被載入模組的引用。所以等到BPage.js
執行完,把控制權交回給APage.js
,這時就一切正常了。
相關文章
- require()、import、import()有哪些區別?UIImport
- require 和 import 詳解UIImport
- import和require的區別ImportUI
- require 和 import 的區別?UIImport
- require和import有啥區別?UIImport
- require和import引用的區別UIImport
- import、require 、export、export default、exports、module exportsImportUIExport
- 談談import和require的區別ImportUI
- import、require、export、module.exports 混合使用詳解ImportUIExport
- JavaScript中使用import 和require打包後實現原理JavaScriptImportUI
- CommonJS,AMD,CMD,ES6,require 和 import 詳解JSUIImport
- 這幾個概念你可能還是沒搞清require、import和exportUIImportExport
- web前端技術分享:詳解模組化require 和 import的區別Web前端UIImport
- 探討ES6的import export default 和CommonJS的require module.exportsImportExportJSUI
- module.exports、exports 、export default之間的差異區別及與require、import的使用ExportUIImport
- #import vs @importImport
- require和require_once的區別UI
- 報錯ReferenceError: require is not defined,找不到requireErrorUI
- require工作原理UI
- require_once()UI
- #import、#include、@import modules區別Import
- sap.ui.require in SAP UI5 and require in nodejsUINodeJS
- require.contextUIContext
- php--include 、requirePHPUI
- nodejs module/requireNodeJSUI
- vue專案實現按需載入的3種方式:vue非同步元件、es提案的import()、webpack的require.ensure()Vue非同步元件ImportWebUI
- Python import相關內容區別介紹( import *** as 、from***import )PythonImport
- from module import 和 import 的區別Import
- include與require、require_once與include_once的區別UI
- php中 include,require,include_once,require_once 的區別PHPUI
- [php]require&require_once&include&include_once的用法與區別PHPUI
- SCSS @importCSSImport
- CSS @importCSSImport
- Import OverImport
- Import DataImport
- export/importExportImport
- Import Error: cannot import name ‘export_saved_modelImportErrorExport
- import tkinter與from tkinter import *的區別Import