一個(gè)缺失已久的特性 — module模塊

1.jpg

在ES6之前,Javascript還不支持原生的模塊化。如果要實(shí)現(xiàn)模塊化,我們要借助一些框架,比如:requireJS或者seaJS等;什么?沒(méi)用過(guò)也沒(méi)聽過(guò)這些框架?沒(méi)關(guān)系,它們不是我們今天要講的重點(diǎn)。

今天的主角是:ES6自帶的模塊化。

模塊化的初衷

也許你要問(wèn)了,好端端的,為什么要模塊化?

現(xiàn)在的web系統(tǒng)越來(lái)越龐大、復(fù)雜,需要團(tuán)隊(duì)分工,多人協(xié)作,大型系統(tǒng)的javascript文件經(jīng)常存在復(fù)雜的依賴關(guān)系,后期的維護(hù)成本會(huì)越來(lái)越高。

JavaScript模塊化正式為了解決這一需求而誕生。

竟然模塊化這么重要,我們看看ES6的module模塊是什么實(shí)現(xiàn)的?

Ps:目前還沒(méi)有瀏覽器支持ES6的module模塊。

假設(shè)現(xiàn)在有兩個(gè)js文件,分別是module-A.js和module-B.js,我們把它們視為兩個(gè)模塊。

帶著這個(gè)假設(shè),下面我們來(lái)學(xué)習(xí)module模塊的幾個(gè)概念以及它們的含義。

模塊Module

模塊Module:一個(gè)模塊,就是一個(gè)對(duì)其他模塊暴露自己的屬性或者方法的文件。

在這里,我們會(huì)把module-A.js和module-B.js分別當(dāng)作兩個(gè)模塊(moduleA模塊和moduleB模塊)來(lái)對(duì)待和處理。用這兩個(gè)模塊來(lái)演示如何暴露一個(gè)模塊的屬性或方法。

導(dǎo)出Export

導(dǎo)出Export:作為一個(gè)模塊,它可以選擇性地給其他模塊暴露(提供)自己的屬性和方法,供其他模塊使用。

導(dǎo)入Import

導(dǎo)入Import:作為一個(gè)模塊,可以根據(jù)需要,引入其他模塊的提供的屬性或者方法,供自己模塊使用。

模塊化的實(shí)現(xiàn)

帶著這三個(gè)概念,我們來(lái)演示一下它們的基本用法:

moduleB模塊代碼:


    //---module-B.js文件---

    //導(dǎo)出變量:name
    export var name = "前端君"; 

模塊B我們使用關(guān)鍵字export關(guān)鍵字,對(duì)外暴露了一個(gè)屬性:name的值為:字符串“前端君”。一個(gè)關(guān)鍵字,一句代碼就實(shí)現(xiàn)了,是不是很簡(jiǎn)單。

模塊B演示了導(dǎo)出,接下來(lái)我們用模塊A來(lái)演示如何導(dǎo)入。

moduleA模塊代碼:


    //---module-A.js文件---

    //導(dǎo)入 模塊B的屬性 name
    import { name } from "./module-B.js";
    console.log(name)
    //打印結(jié)果:前端君

模塊A我們使用關(guān)鍵字import導(dǎo)入了模塊B的name屬性,并且賦值給變量name。關(guān)鍵字from的作用是指定你想要引入的模塊,我們這里指定的是module-B.js文件,也就是上面的模塊B。打印結(jié)果:“前端君”正是模塊B的對(duì)外暴露的屬性。

批量導(dǎo)出

對(duì)于模塊B,如果你想導(dǎo)出(暴露)多個(gè)屬性和方法的話,你可以這樣實(shí)現(xiàn):


    //屬性name
    var name = "前端君";
    //屬性age
    var age  = 25;
    //方法 say
    var say = function(){
        console.log("say hello");
    }

    //批量導(dǎo)出
    export {name,age,say}

上面,我們定義了2個(gè)屬性和1個(gè)方法,最后用一個(gè)對(duì)象實(shí)現(xiàn)將它們批量導(dǎo)出。我們更推薦的是使用這種方法實(shí)現(xiàn)導(dǎo)出,因?yàn)?strong>當(dāng)對(duì)外暴露的屬性和方法較多的時(shí)候,這種方法可以更直觀地看出當(dāng)前模塊暴露了哪些變量。

而對(duì)于這種批量導(dǎo)出,我們導(dǎo)入的時(shí)候怎么對(duì)應(yīng)上呢?


    //---module-A.js文件---

    //導(dǎo)入 模塊B的屬性 name
    import { name,age,say } from "./module-B.js";

    console.log(name)
    //打印結(jié)果:前端君

    console.log(age)
    //打印結(jié)果:25

    say()
    //打印結(jié)果:say hello

同樣,我們使用多個(gè)同名變量就可以獲取對(duì)應(yīng)的屬性和方法,變量名字必須跟導(dǎo)出的一致才能準(zhǔn)確獲取,位置順序無(wú)要求。

重命名導(dǎo)入的變量

也許你突發(fā)奇想,想給導(dǎo)入的變量換一個(gè)名字的話,你可以這樣做:


    import { name as myname } from "./module-B.js";

    console.log(myname)
    //打印結(jié)果:前端君

使用關(guān)鍵字as,可以實(shí)現(xiàn)給變量name更換名字為myname。最后正確輸出myname的值:“前端君”。

整體導(dǎo)入

我們還可以使用星號(hào)*實(shí)現(xiàn)整體導(dǎo)入:


    //使用*實(shí)現(xiàn)整體導(dǎo)入
    import * as obj from "./module-B.js";

    console.log(obj.name)
    //結(jié)果:"前端君"

    console.log(obj.age)
    //結(jié)果:25

    obj.say();
    //結(jié)果:say hello

使用星號(hào)符將模塊B提供的所有屬性和方法整體導(dǎo)入*賦值給變量obj,我們可以點(diǎn)運(yùn)算符來(lái)獲取它的屬性和方法。

默認(rèn)導(dǎo)出

默認(rèn)導(dǎo)出,每個(gè)模塊支持我們導(dǎo)出一個(gè)沒(méi)有名字的變量,我們使用關(guān)鍵語(yǔ)句export default來(lái)實(shí)現(xiàn)


    export default function(){
        console.log("I am default Fn");
    }

我們使用export default關(guān)鍵字對(duì)外導(dǎo)出一個(gè)匿名函數(shù),導(dǎo)入這個(gè)模塊的時(shí)候,可以為這個(gè)匿名函數(shù)取任意的名字,我們?cè)囈幌聦?dǎo)入上面那個(gè)匿名函數(shù):


    //取任意名字均可
    import sayDefault from "./module-B.js";

    sayDefault();
    //結(jié)果:I am default Fn

同樣是使用import關(guān)鍵字導(dǎo)入模塊B,但是這次不需要使用大括號(hào){ }。我們使用新的名字:sayDefault來(lái)代替導(dǎo)入的匿名函數(shù),最后調(diào)用一下,打印結(jié)果正是模塊B默認(rèn)導(dǎo)出的匿名函數(shù)的執(zhí)行效果。

注意事項(xiàng)

1、聲明的變量,對(duì)外都是只讀的


    //---module-B.js文件------
    var name = "前端君"
    export {name}

    //---module-A.js文件------
    import {name} from "./module-B.js";
    name = "修改字符串變量";
    //報(bào)錯(cuò):name is read-only

上面的代碼片段包含了2個(gè)模塊,其中,模塊B導(dǎo)出了字符串變量name,模塊A導(dǎo)出變量name之后試圖修改它的值,結(jié)果報(bào)錯(cuò)。

但是,如果模塊B導(dǎo)出的是對(duì)象類型的值,就可修改。


    //---module-B.js文件---
    var person = {"name":"前端君"}
    export { person }

    //---module-A.js文件------
    import {person} from "./module-B.js";
    person.name = "修改字符串變量";
    //修改成功

上面的代碼片段包含了2個(gè)模塊,模塊B導(dǎo)出了對(duì)象person,模塊A導(dǎo)入后,對(duì)其屬性name進(jìn)行修改,結(jié)果修改成功,這一點(diǎn)大家要注意,并不是所有導(dǎo)出的變量都不可修改,對(duì)象類型就可修改。

2、導(dǎo)入不存在的變量,值為undefined。


    //---module-B.js文件---
    var name = "前端君";
    export {name}

    //---module-A.js文件------
    import { height } from "./module-B.js";
    console.log(height);
    //打印結(jié)果:undefined

模塊A想導(dǎo)入的變量height,在模塊B中并沒(méi)有提供,但這不會(huì)拋出異常,只是height的值為undefined。

module模塊的講解就到這里,ES6整個(gè)系列的連載也算完滿結(jié)束,但是ES6的學(xué)起還沒(méi)結(jié)束,周末會(huì)推出一期增值服務(wù),如果你想進(jìn)一步鞏固這么多天來(lái)的ES6學(xué)習(xí),那么,敬請(qǐng)期待!

本節(jié)小結(jié)

總結(jié):ES6自帶了module模塊,但目前瀏覽器并沒(méi)有支持。我們可以輕松實(shí)現(xiàn)導(dǎo)入導(dǎo)出,批量導(dǎo)出,默認(rèn)導(dǎo)入export default,使用星號(hào)符*整體導(dǎo)入,as關(guān)鍵字實(shí)現(xiàn)重命名。

作者口述

OK,那么ES6的基本教程就到這里結(jié)束了,那么以后我還會(huì)出ES6的高階文章.那么從明天開始我開始寫Vue框架的文章.謝謝大家一直以來(lái)的支持.

在這里我給大家準(zhǔn)備了很多的學(xué)習(xí)資料

其實(shí)你與阿里工程師的差距只差這些東西

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前面的話 ??JS用"共享一切"的方法加載代碼,這是該語(yǔ)言中最易出錯(cuò)且容易令人感到困惑的地方。在ES6以前,在應(yīng)用...
    CodeMT閱讀 2,977評(píng)論 0 5
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 3,720評(píng)論 2 27
  • 模塊通常是指編程語(yǔ)言所提供的代碼組織機(jī)制,利用此機(jī)制可將程序拆解為獨(dú)立且通用的代碼單元。所謂模塊化主要是解決代碼分...
    MapleLeafFall閱讀 1,251評(píng)論 0 0
  • 點(diǎn)擊此鏈接閱讀體驗(yàn)更好Es6中的模塊默認(rèn)導(dǎo)入導(dǎo)出及加載順序 前言 在前面一Es6中的模塊化Module,導(dǎo)入(im...
    itclanCoder閱讀 3,790評(píng)論 0 0
  • 今天,我邀請(qǐng)幾個(gè)朋友回老家祭棗神、參加曬棗活動(dòng)。 老鄉(xiāng)們熱情招待我們,特以家鄉(xiāng)的風(fēng)俗,唱山歌與我們歡笑。我們興趣大...
    桃園春曉閱讀 706評(píng)論 2 7

友情鏈接更多精彩內(nèi)容