在ES6之前,Javascript還不支持原生的模塊化。如果要實現模塊化,我們要借助一些框架,比如:requireJS或者seaJS等;什么?沒用過也沒聽過這些框架?沒關系,它們不是我們今天要講的重點。
今天的主角是:ES6自帶的模塊化。
模塊化的初衷
也許你要問了,好端端的,為什么要模塊化?
現在的web系統越來越龐大、復雜,需要團隊分工,多人協作,大型系統的javascript文件經常存在復雜的依賴關系,后期的維護成本會越來越高。
JavaScript模塊化正式為了解決這一需求而誕生。
竟然模塊化這么重要,我們看看ES6的module模塊是什么實現的?
Ps:目前還沒有瀏覽器支持ES6的module模塊。
假設現在有兩個js文件,分別是module-A.js和module-B.js,我們把它們視為兩個模塊。
帶著這個假設,下面我們來學習module模塊的幾個概念以及它們的含義。
模塊Module
模塊Module:一個模塊,就是一個對其他模塊暴露自己的屬性或者方法的文件。
在這里,我們會把module-A.js和module-B.js分別當作兩個模塊(moduleA模塊和moduleB模塊)來對待和處理。用這兩個模塊來演示如何暴露一個模塊的屬性或方法。
導出Export
導出Export:作為一個模塊,它可以選擇性地給其他模塊暴露(提供)自己的屬性和方法,供其他模塊使用。
導入Import
導入Import:作為一個模塊,可以根據需要,引入其他模塊的提供的屬性或者方法,供自己模塊使用。
模塊化的實現
帶著這三個概念,我們來演示一下它們的基本用法:
moduleB模塊代碼:
//---module-B.js文件---
//導出變量:name
export var name = "前端君";
模塊B我們使用關鍵字export關鍵字,對外暴露了一個屬性:name的值為:字符串“前端君”。一個關鍵字,一句代碼就實現了,是不是很簡單。
模塊B演示了導出,接下來我們用模塊A來演示如何導入。
moduleA模塊代碼:
//---module-A.js文件---
//導入 模塊B的屬性 name
import { name } from "./module-B.js";
console.log(name)
//打印結果:前端君
模塊A我們使用關鍵字import導入了模塊B的name屬性,并且賦值給變量name。關鍵字from的作用是指定你想要引入的模塊,我們這里指定的是module-B.js文件,也就是上面的模塊B。打印結果:“前端君”正是模塊B的對外暴露的屬性。
批量導出
對于模塊B,如果你想導出(暴露)多個屬性和方法的話,你可以這樣實現:
//屬性name
var name = "前端君";
//屬性age
var age = 25;
//方法 say
var say = function(){
console.log("say hello");
}
//批量導出
export {name,age,say}
上面,我們定義了2個屬性和1個方法,最后用一個對象實現將它們批量導出。我們更推薦的是使用這種方法實現導出,因為當對外暴露的屬性和方法較多的時候,這種方法可以更直觀地看出當前模塊暴露了哪些變量。
而對于這種批量導出,我們導入的時候怎么對應上呢?
//---module-A.js文件---
//導入 模塊B的屬性 name
import { name,age,say } from "./module-B.js";
console.log(name)
//打印結果:前端君
console.log(age)
//打印結果:25
say()
//打印結果:say hello
同樣,我們使用多個同名變量就可以獲取對應的屬性和方法,變量名字必須跟導出的一致才能準確獲取,位置順序無要求。
重命名導入的變量
也許你突發奇想,想給導入的變量換一個名字的話,你可以這樣做:
import { name as myname } from "./module-B.js";
console.log(myname)
//打印結果:前端君
使用關鍵字as,可以實現給變量name更換名字為myname。最后正確輸出myname的值:“前端君”。
整體導入
我們還可以使用星號*實現整體導入:
//使用*實現整體導入
import * as obj from "./module-B.js";
console.log(obj.name)
//結果:"前端君"
console.log(obj.age)
//結果:25
obj.say();
//結果:say hello
使用星號符將模塊B提供的所有屬性和方法整體導入*賦值給變量obj,我們可以點運算符來獲取它的屬性和方法。
默認導出
默認導出,每個模塊支持我們導出一個沒有名字的變量,我們使用關鍵語句export default來實現:
export default function(){
console.log("I am default Fn");
}
我們使用export default關鍵字對外導出一個匿名函數,導入這個模塊的時候,可以為這個匿名函數取任意的名字,我們試一下導入上面那個匿名函數:
//取任意名字均可
import sayDefault from "./module-B.js";
sayDefault();
//結果:I am default Fn
同樣是使用import關鍵字導入模塊B,但是這次不需要使用大括號{ }。我們使用新的名字:sayDefault來代替導入的匿名函數,最后調用一下,打印結果正是模塊B默認導出的匿名函數的執行效果。
注意事項
1、聲明的變量,對外都是只讀的。
//---module-B.js文件------
var name = "前端君"
export {name}
//---module-A.js文件------
import {name} from "./module-B.js";
name = "修改字符串變量";
//報錯:name is read-only
上面的代碼片段包含了2個模塊,其中,模塊B導出了字符串變量name,模塊A導出變量name之后試圖修改它的值,結果報錯。
但是,如果模塊B導出的是對象類型的值,就可修改。
//---module-B.js文件---
var person = {"name":"前端君"}
export { person }
//---module-A.js文件------
import {person} from "./module-B.js";
person.name = "修改字符串變量";
//修改成功
上面的代碼片段包含了2個模塊,模塊B導出了對象person,模塊A導入后,對其屬性name進行修改,結果修改成功,這一點大家要注意,并不是所有導出的變量都不可修改,對象類型就可修改。
2、導入不存在的變量,值為undefined。
//---module-B.js文件---
var name = "前端君";
export {name}
//---module-A.js文件------
import { height } from "./module-B.js";
console.log(height);
//打印結果:undefined
模塊A想導入的變量height,在模塊B中并沒有提供,但這不會拋出異常,只是height的值為undefined。
module模塊的講解就到這里,ES6整個系列的連載也算完滿結束,但是ES6的學起還沒結束,周末會推出一期增值服務,如果你想進一步鞏固這么多天來的ES6學習,那么,敬請期待!
本節小結
總結:ES6自帶了module模塊,但目前瀏覽器并沒有支持。我們可以輕松實現導入導出,批量導出,默認導入export default,使用星號符*整體導入,as關鍵字實現重命名。
作者口述
OK,那么ES6的基本教程就到這里結束了,那么以后我還會出ES6的高階文章.那么從明天開始我開始寫Vue框架的文章.謝謝大家一直以來的支持.
在這里我給大家準備了很多的學習資料