ES6 module模組 import export
一個模組就是一個獨立的檔案。該檔案內部的所有變數,外部無法獲取。ES6中如果你希望外部能夠讀取模組內部的某個變數,就必須使用export關鍵字輸出該變數,其他 JS 檔案就可以通過import命令載入這個模組。
//export.js
export var foo = 'bar';
瀏覽器載入 ES6 模組,<script>
加入type="module"
屬性。
//xx.html
<script type="module">
import {foo} from './js/export.js'
console.log(foo);
</script>
1️⃣ES6 模組與 CommonJS 模組的差異
CommonJS 模組是 Node.js 專用的,與 ES6 模組不相容。
- CommonJS 模組輸出的是一個值的拷貝,ES6 模組輸出的是值的引用。
- CommonJS 模組是執行時載入,ES6 模組是編譯時輸出介面。
- CommonJS 模組的require()是同步載入模組,ES6 模組的import命令是非同步載入,有一個獨立的模組依賴的解析階段。
CommonJS 載入的是一個物件(即module.exports屬性),該物件只有在指令碼執行完才會生成。
// CommonJS模組 ES5
let { stat, exists, readfile } = require('fs');
// 等同於
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
載入fs模組(即載入fs的所有方法),生成一個物件(_fs),然後再從這個物件上面讀取 3 個方法。
這種載入稱為“執行時載入”,因為只有執行時才能得到這個物件,導致完全沒辦法在編譯時做“靜態優化”。
?module.exports與require
// lib.js
var counter = 3;
function incCounter() {
counter++;
}
module.exports = {
counter: counter,
incCounter: incCounter,
};
// main.js
var mod = require('./lib');
console.log(mod.counter); // 3
mod.incCounter();
console.log(mod.counter); // 3
ES6 模組不是物件,它的對外介面只是一種靜態定義,在程式碼靜態解析階段就會生成。
// ES6模組
import { stat, exists, readFile } from 'fs';
從fs模組載入 3 個方法,其他方法不載入。這種載入稱為“編譯時載入”或者“靜態載入”。效率要比 CommonJS 模組的載入方式高。當然,這也導致了沒法引用 ES6 模組本身,因為它不是物件。
2️⃣ES6 module
瀏覽器對於帶有type="module"
的<script>
,都是非同步載入,不會造成堵塞瀏覽器,即等到整個頁面渲染完,再執行模組指令碼,等同於開啟了<script>
標籤的defer
屬性。有多個type="module"
的<script>
,按在頁面出現的順序執行。但若使用了async屬性,就會轉為async的行為特徵。
程式碼是在模組作用域之中執行,而不是在全域性作用域執行。
ES6 的模組自動採用嚴格模式,不管你有沒有在模組頭部加上"use strict"。比如:這就會讓this受到了限制,頂層的this指向undefined,更多關於嚴格模式知識點看下文。
export
1.兩種寫法
//export.js
//寫法一
export let token='xx';
let bar='bar';
function foo(name){console.log(name);}
//寫法二
export {bar,foo}
2.別名 as
export {bar as baz,bar as bac}
3.對外介面必須與模組內部的變數建立一對一對應關係
// 報錯
export 1;//沒有提供對外的介面 只是一個值
// 報錯
var m = 1;
export m;//沒有提供對外的介面 只是一個值
// 報錯
function f() {}
export f;//沒有提供對外的介面 只是一個值(函式體)
4.export語句輸出的介面,與其對應的值是動態繫結關係
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);
<script type="module">
import {foo} from './js/export.js'
console.log(foo);
setTimeout(() => console.log(foo), 500);
</script>
5.export命令可以出現在模組的任何位置,只要處於模組頂層就可以
function foo() {
export default 'bar' // SyntaxError
}
foo()
import
1.寫法
import {foo} from './js/export.js'
2.別名 as
import {foo as koo} from './js/export.js'
3.import命令輸入的變數都是隻讀的(本質是輸入介面)
值不可變,物件存的是引用,引用地址沒變即可。
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
import {obj} from './xxx.js'
obj.foo = 'hello'; // 合法操作
4.import命令具有提升效果,會提升到整個模組的頭部,首先執行。
import命令是編譯階段執行的,在程式碼執行之前。
foo();
import { foo } from 'my_module';
5.import後面的from指定模組檔案的位置,若是一個模組名,需要配置檔案指定模組位置
import React from 'React';
import { myMethod } from 'util';
6.import語句會執行所載入的模組
import 'lodash';//上面程式碼僅僅執行lodash模組,但是不輸入任何值。
7.一次全部匯入,模組整體載入* as 別名
import * as k from './js/export.js'
console.log(k.foo);
export default
一個模組只能有一個預設輸出。import預設輸出時不需要大括號,且可隨意起名字。
//export.js
function foo() {
console.log('foo');
}
export let bar=1
export default foo;
//xx.html
<script type="module">
import customName,{bar} from './js/export.js'
customName(); // 'foo'
console.log(bar);//1
</script>
本質上,export default就是輸出一個叫做default的變數或方法,然後系統允許你為它取任意名字。
function add(x, y) {
return x * y;
}
export {add as default};
import { default as foo } from 'modules';
// 正確
export var a = 1;
// 正確
var a = 1;
export default a;//等價於 export default 1;
// 錯誤
export default var a = 1;
impot() 動態載入模組
import和export命令只能在模組的頂層,固然有利於編譯器提高效率,但也導致無法在執行時載入模組。
假如要判斷引入模組,難道要寫成require方法?不必!新推出了impot()方法支援動態載入模組。返回的是promise
物件。
let a;
if(true){
a=import('./js/export.js');
}
console.log(a)//Promise {<pending>}
a.then(({foo, bar}) => {//foo和bar都是export.js的輸出介面
// ...·
});
嚴格模式
模組預設是嚴格模式
- 變數必須宣告後再使用
- 函式的引數不能有同名屬性,否則報錯
- 不能使用with語句
- 不能對只讀屬性賦值,否則報錯
- 不能使用字首 0 表示八進位制數,否則報錯
- 不能刪除不可刪除的屬性,否則報錯
- 不能刪除變數delete prop,會報錯,只能刪除屬性delete global[prop]
- eval不會在它的外層作用域引入變數
- eval和arguments不能被重新賦值
- arguments不會自動反映函式引數的變化
- 不能使用arguments.callee
- 不能使用arguments.caller
- 禁止this指向全域性物件
- 不能使用fn.caller和fn.arguments獲取函式呼叫的堆疊
- 增加了保留字(比如protected、static和interface)
參考文件:
Module 的語法
相關文章
- ES6模組化之export和import的用法ExportImport
- import、require 、export、export default、exports、module exportsImportUIExport
- 探討ES6的import export default 和CommonJS的require module.exportsImportExportJSUI
- ES6 模組語法——export 命令Export
- node識別es6的 import/exportImportExport
- ES6 模組語法——import 命令Import
- [ES6深度解析]15:模組 Module
- 詳解es6的export和import命令ExportImport
- export/importExportImport
- ES6規範import和export用法總結ImportExport
- 通過 babel-node 執行 ES6 import/export 語法BabelImportExport
- Nodejs中exports和module.exports與ES6中的export default 和 export 區別NodeJSExport
- import,export的支援[nodejs]ImportExportNodeJS
- Python模組(module)Python
- Import Error: cannot import name ‘export_saved_modelImportErrorExport
- 6.exports、module.exports、export、export defalutExport
- Export/import Datas To/from a Csv FileExportImport
- python基礎--自定義模組、import、from......import......PythonImport
- 新手關於import/export的理解ImportExport
- ES6:export 與 export default 區別Export
- JavaScript ES6中,export與export defaultJavaScriptExport
- module.exports、exports 、export default之間的差異區別及與require、import的使用ExportUIImport
- Python之外掛模式(使用import_module匯入子模組)Python模式Import
- JavaScript中的export、export default、exports和module.exports(export、export default、exports使用詳細)JavaScriptExport
- ES6模組
- ES6 export 和 export default的區別Export
- ES6 export && export default 差異總結Export
- go 語言模組匯入importGoImport
- 前端模組化之ES Module前端
- js module bundle 模組捆綁JS
- ES6模組化
- ES6 - 模組化
- JS/TS 的 import 和 export 用法小結JSImportExport
- module.exports與export那些事兒Export
- 前端模組化IIFE,commonjs,AMD,UMD,ES6 Module規範超詳細講解前端JS
- Java 9 的模組(Module)系統Java
- webpack 模組熱更新 Hot Module ReplacementWeb
- [Typescript] Verbatim Module Syntax Enforces Import TypeTypeScriptBATImport