在原始的 JS 時代,是沒有模塊化的概念的,隨着前端項目的愈來愈大,而且前端的地位愈來愈主要,急需模塊化的概念引入進來。在 ES6 以前,社區制定了一些模塊化的方案,如:CommonJS 和 AMD。ES6 以後這兩個正在慢慢的被 import 和 export 所取代。前端
這讓我想起了以前面試的時候一個面試官問我 ES6 爲何要引入 import 和 export,個人回答是爲了模塊化的加載,避免全局污染,而後他問了一個讓我至今難忘的問題,爲何是 import 和 export 這兩個單詞????😓😓😓 當時的我頓時語塞,只能弱弱的回答一句,JS 規範的....git
export 用於規定模塊對外的接口,無論你是否認義,export 導出的模塊都是處於嚴格模式,不能用在嵌入式腳本中。github
export 導出的語法有兩種:面試
如在 a.js 文件中,想要導出幾個變量,咱們能夠寫成以下兩種形式。編程
// a.js
// 第一種
export var a = 1;
export var b = 2;
export var c = 3;
// 第二種
var a = 1;
var b = 2;
var c = 3;
export { a, b, c };
複製代碼
以上兩種形式是等價的,可是傾向於第二種寫法,由於第二種寫法便於閱讀,能一眼看出要導出的變量是什麼。api
除了能導出變量,咱們在開發中應用最多的就是導出函數和類。markdown
export function foo(a, b) {
return a + b;
}
// 等價於
function foo(a, b) {
return a + b;
}
export { foo };
// 應用到箭頭函數
const foo = (a, b) => a + b;
export { foo };
複製代碼
導出的名稱除了能夠是該變量本來的名稱外,還能夠經過 as 關鍵詞對其重命名。app
var a = 1;
export { a as b, a as c };
複製代碼
上述經過 as 關鍵詞對 a 變量進行了重命名,而且同一個變量能夠重命名屢次。模塊化
有一點值得注意的是,export 輸出的必定是一個變量,變量,變量,重要的事情說三遍。函數
// 第一種
export 1; // 報錯
// 第二種
var a = 1;
export a; // 報錯
複製代碼
上述兩種導出接口的方式均報錯,由於輸出均不是變量,第二種雖然 a 是變量,可是實際上跟第一種是同樣的,只是變換了一下寫法,函數和類也是如此。
咱們能夠經過 export default 命名對模塊進行默認導出,而且一個模塊中只能有一個默認導出。
export default function (a, b) {
return a + b;
}
export default function foo(a, b) {
return a + b;
}
export default 1;
var a = 1;
export default a;
複製代碼
上一節咱們說 export 最重要的是導出的接口是變量,在默認導出中發現若是導出的不是變量的話也是能夠的,這是由於 default 其實就是一個變量,因此能夠導出的不是一個變量,可是 default 後面跟着的是一個變量話,會報錯。
export default var a = 1; // 報錯
複製代碼
import 命令用於輸入其餘模塊提供的功能。export 有兩種語法形式,對應的 import 也有兩種語法形式
// a.js
var a = 1;
var b = 2;
export { a, b };
import { a, b } from "a.js";
複製代碼
當 export 輸出模塊接口時,import 要用大括號來進行導入,默認狀況下導入的名稱要和輸出的名稱一致。若是想要更改導入的名稱,咱們一樣能夠用 as 關鍵詞進行重命名。
// a.js
var a = 1;
var b = 2;
export { a, b };
import { a as a1, b as b1 } from "a.js";
複製代碼
// a.js
var a = 1;
export default a;
import a from "a.js";
複製代碼
也能夠和上一節一塊使用:
// a.js
var a = 1;
var b = 2;
var c = 3;
export default c;
export { a, b };
import c, { a, b } from "a.js";
複製代碼
import 表達式引入進來的全部模塊都是隻讀形式,也就是說,不容許在加載模塊的腳本里面,改寫模塊。
import { a } from "a.js";
a = {}; // Syntax Error : 'a' is read-only;
複製代碼
可是若是引入的模塊是一個對象類型的話,它的屬性是能夠更改。
import { a } from "a.js";
a.name = "Jack"; // 合法
複製代碼
雖然說此功能合法,可是在實際開發中仍是要慎用。
import 後面的 from 指定模塊文件的位置,能夠是相對路徑,也能夠是絕對路徑,.js 後綴能夠省略。若是隻是模塊名,不帶有路徑,那麼必須有配置文件,告訴 JavaScript 引擎該模塊的位置。
import { myMethod } from "util";
複製代碼
上面代碼中,util 是模塊文件名,因爲不帶有路徑,必須經過配置,告訴引擎怎麼取到這個模塊。
import 還有一個特性時,import 具備提高,會提高到整個文件的最頂端,首先執行。
foo(); // 不會報錯
import { foo } from "a.js";
複製代碼
上述例子不會報錯的緣由就是由於 import 具備提高,提高到了 foo()以前,首先執行。
除此以外,import 不能當作表達式和變量,不能參與運算。
import {'1' + foo} from 'a.js' // 報錯
// 報錯
if (x === 1) {
import { foo } from 'module1';
} else {
import { foo } from 'module2';
}
複製代碼
import 還能夠僅僅導入模塊,但不作任何的輸入。
import "a.js";
複製代碼
這將運行模塊中的全局代碼, 但實際上不導入任何值。
與上述相反的是,將模塊所有導入,總體加載,而且一樣支持經過 as 關鍵詞重命名。
import * from 'a.js'
import * as b from 'a.js'
複製代碼
若是在一個模塊中先輸入後輸出同一個模塊,那能夠運用 export 和 import 複合寫法,即 export...from...
export { foo, bar } from "a.js";
// 能夠簡單的理解爲
import { foo, bar } from "a.js";
export { foo, bar };
複製代碼
值得注意的是,上述的 foo 和 bar 並無引入到當前模塊,當前模塊至關於一箇中轉站,只是對 foo 和 bar 進行轉發。
一樣咱們依然能夠對轉發的模塊進行重命名,並且能夠經過*對其所有轉發。
export { foo as foo1 } from "a.js";
export * from "a.js";
複製代碼
在 ES2020 中還能夠對*經過 as 關鍵詞進行重命名。
export * as a from "a.js";
// 等價於
import * as a from "a.js";
export { a };
複製代碼
除此以外,在 export 和 import 複合寫法中,咱們能夠對默認模塊進行轉發。
export { default } from "a.js";
複製代碼
是否是感受很奇怪,沒錯,我第一次見到的時候也很奇怪,可是後期想了一下,export...from...導入變量,default 也是變量的一種,因此這種也就不奇怪了。
依舊能夠經過 as 進行重命名。
export { default as foo } from "a.js";
複製代碼
而且還能夠將具名接口改成默認接口。
export { foo as default } from "a.js";
// 等價於
import { foo } from "a.js";
export default foo;
複製代碼
ES2020 中新增了 import(),主要是爲了解決沒法動態導入的問題,由於以前也說過,JS 爲了靜態分析優化,因此 import 必須放在整個模塊的頂部,而且不能和表達式混合使用,這在有些場景,尤爲是 Node 中非常麻煩,這也是爲何 Node 仍是偏向用 require 導入接口的緣由之一。
使用 import()動態加載接口的用法很簡單,括號內填寫要動態導入接口就能夠。
import("a.js");
複製代碼
import()會返回一個 Promise 對象。
import("a.js").then((value) => console.log(value));
複製代碼
import()的應用,最直觀的就是應用在動態加載組件上,咱們能夠看到 dva 中dva/dynamic其內部主要就是運用了 import(),對組件和路由進行動態加載,達到優化目的。
import dynamic from "dva/dynamic";
const UserPageComponent = dynamic({
app,
models: () => [import("./models/users")],
component: () => import("./routes/UserPage"),
});
複製代碼
這次也是對export和import有了個從新的認識,也但願對你有所幫助。 點個贊吧!💥🧡💖
以爲還能夠的,麻煩走的時候能給點個贊,你們一塊兒學習和探討!
還能夠關注個人博客但願能給個人github上點個Start,小夥伴們必定會發現一個問題,個人全部用戶名幾乎都與番茄有關,由於我真的很喜歡吃番茄❤️!!!
想跟車不迷路的小夥還但願能夠關注公衆號 前端老番茄 或者掃一掃下面的二維碼👇👇👇。
我是一個編程界的小學生,您的鼓勵是我不斷前進的動力,😄但願能一塊兒加油前進。
本文使用 mdnice 排版