摘要:模塊什么是模塊什么是模塊化玩過游戲的朋友應(yīng)該知道,一把裝配完整的步槍,一般是槍身消音器倍鏡握把槍托。更重要的是,其它大部分語言都支持模塊化。這一點與規(guī)范完全不同。模塊輸出的是值的緩存,不存在動態(tài)更新。
1.模塊 1.1 什么是模塊?什么是模塊化?
玩過FPS游戲的朋友應(yīng)該知道,一把裝配完整的M4步槍,一般是槍身+消音器+倍鏡+握把+槍托。
如果把M4步槍看成是一個頁面的話,那么我們可以做如下類比
槍身 ->
消音器 ->
倍鏡 ->
握把 ->
槍托 ->
OK,你剛才做了一件事情,就是把m4步槍拆成了五個部分,你拆分的每一個部分就是一個模塊【module】,你拆分的這個過程就是模塊化【modularization】。
模塊化是一種編程思想,其核心就是拆分任務(wù),把復(fù)雜問題簡單化,這樣一來既方便多人分工協(xié)作,又可以幫助我們迅速定位問題
方便多人分工協(xié)作 —— 可以不同的人開發(fā)不同的模塊,再組合,大大增加團隊效率
幫助我們迅速定位問題 —— 后坐力太大,那八成是槍托或握把的問題;聲音過大,那八成是消音器的問題。
1.2 模塊化的血淚史下面用一個小栗子講一講模塊化的發(fā)展史
龔先生和棚先生一起接了一個項目,他們倆需要分別實現(xiàn)一些功能,很簡單,就是Console出來自己的變量a
于是他們倆一合計,安排龔先生的代碼多帶帶放在script1.js里寫,棚先生的代碼多帶帶放在script2.js里寫,然后用script標(biāo)簽分別引入
// script1.js文件 var a = 1 console.log(a)
// script2.js文件 var a = 2 console.log(a)
很快他們遇到了第一個問題 —— 變量命名沖突
尤其是包含了異步的時候,會出現(xiàn)如下情況
// script1.js文件 var a = 1 setTimeout(()=>{ console.log(a) // 我們想console出來1,卻console出了2 },1000)
// script2.js文件 var a = 2 console.log(a)
上面的問題明顯是由于a是一個全局變量導(dǎo)致的,所以解決思路也很明確——造一個局部變量唄
局部變量ES5時代使用立即執(zhí)行函數(shù)制造局部變量
// script1.js文件 !function(){ var a = 1 setTimeout(()=>{ console.log(a) // 這下是2了 },1000) }() // 下面有5000行代碼
// script2.js文件 console.log(2)
ES6時代直接使用塊級作用域+let
// script1.js文件 { let a = 1 setTimeout(()=>{ console.log(a) // 這下是2了 },1000) }
// script2.js文件 { let a = 2 console.log(a) }通過window連接各個模塊
后來公司招了一個前端大佬,說現(xiàn)在只能由他來控制什么時候console變量,于是他新建了一個control.js文件
并通過window對象連接script1.js和scirpt2.js
// script1.js文件 { let a = 1 window.module1 = function() { console.log(a) } }
// script2.js文件 { let a = 2 window.module2 = function() { console.log(a) } }
// control.js文件 setTimeout(()=>{ window.module1() },1000) window.module2()
這個時候,非常重要的一點就是window是一個全局變量并且充當(dāng)了一個公用倉庫,這個倉庫有兩個關(guān)鍵作用,存【導(dǎo)出】和取【依賴】
// script1.js文件 { let a = 1 // 把這個函數(shù)存放進window,就是導(dǎo)出到window window.module1 = function() { console.log(a) } }
// control.js文件 setTimeout(()=>{ // 我們從window里取出module1函數(shù)進行調(diào)用,就是依賴了script1.js文件 window.module1() },1000) window.module2()依賴加載的順序
煩人的產(chǎn)品對需求又進行了更改,給了一個name.js文件
// name.js文件 window.names = ["gongxiansheng","pengxiansheng"]
要求現(xiàn)在龔先生和棚先生需要Console出自己的名字
這還不簡單?幾秒鐘寫好
// script1.js文件 { window.module1 = function() { console.log(window.names[0]) } }
// script2.js文件 { window.module2 = function() { console.log(window.names[1]) } }
// control.js文件 setTimeout(()=>{ window.module1() },1000) window.module2()
但很快他們發(fā)現(xiàn),console出來的都是undefined
前端大佬一眼看出了問題,對他們倆說
你們依賴的代碼一定要在你們自己的代碼前引入,不然是取不到值的;你看我的control.js是不是在你們倆的代碼后面引入的,因為我用到了你們倆的代碼了呀
噢噢,原來是js文件加載順序問題,改一下吧
但是在人多了以后,我們到時候會搞不清楚到底誰依賴了誰,保險起見只能全部都加載,性能浪費了太多,前端大佬搖頭嘆息道
2. ES6的模塊 2.1 ES6之前模塊化的痛點變量沖突
要用window連接各個模塊
依賴需要全部加載
還要TMD注意加載順序
模塊化是ES6的最大的亮點之一,因為在ES6之前的語法里從未有過模塊化的體系,這對開發(fā)大型的、復(fù)雜的項目形成了巨大障礙。因為我們無法對項目進行拆分,無法更好地進行多人協(xié)作開發(fā)。更重要的是,其它大部分語言都支持模塊化。
既然語言不支持,那么如何將模塊化引入JS呢?
前端社區(qū)就自己制定了一些模塊加載方案——這也是CommonJS【服務(wù)器】和AMD、CMD【瀏覽器】的由來。
但是現(xiàn)在ES6引入了模塊化的功能,實現(xiàn)起來非常簡單,完全可以取代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。2.2 import和export的用法
import和export語法較為簡單,大家去MDN可以看非常詳細(xì)的講解,筆者在這里知識用注釋簡單介紹一下export語法
// 命名導(dǎo)出 export { name1, name2, …, nameN }; export { variable1 as name1, variable2 as name2, …, nameN }; export let name1, name2, …, nameN; // also var export let name1 = …, name2 = …, …, nameN; // also var, const export function FunctionName() {...} export class ClassName {...} // 默認(rèn)導(dǎo)出 export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; // 將其它模塊內(nèi)的導(dǎo)出作為當(dāng)前文件的導(dǎo)出 export * from …; export { name1, name2, …, nameN } from …; export { import1 as name1, import2 as name2, …, nameN } from …;import用法
import defaultExport from "module-name"; // 導(dǎo)入默認(rèn)默認(rèn)變量 import * as name from "module-name"; // 將模塊內(nèi)所有變量導(dǎo)出,并掛載到name下【name是一個module對象】。什么要有as——為了防止export出來的變量命名沖突 import { export } from "module-name"; // 導(dǎo)入某一個變量 import { export as alias } from "module-name"; // 導(dǎo)入某一個變量并重命名 import { export1 , export2 } from "module-name"; // 導(dǎo)入兩個變量 import { export1 , export2 as alias2 , [...] } from "module-name"; // 導(dǎo)入多個變量,同時可以給導(dǎo)入的變量重命名 import defaultExport, { export [ , [...] ] } from "module-name"; // 導(dǎo)入默認(rèn)變量和多個其它變量 import defaultExport, * as name from "module-name"; // 導(dǎo)入默認(rèn)變量并重新命名 import "module-name"; // 導(dǎo)入并加載該文件【注意文件內(nèi)的變量必須要通過export才能被使用】 var promise = import(module-name); // 異步的導(dǎo)入使用import和export改寫第一節(jié)的代碼
// name.js文件 let names = ["gongxiansheng","pengxiansheng"] export default names
// script1.js import names from "./name.js" let module1 = function () { console.log(names[0]) } export default module1
// script2.js import names from "./name.js" let module2 = function() { console.log(names[1]) } export default module2
// control.js import module1 from "./script1.js" import module2 from "./script2.js" setTimeout(() => { module1() }, 1000) module2()
2.3 拓展:import和export的一些運行原理 2.3.1 ES6 模塊輸出的是值的引用,輸出接口會動態(tài)綁定
其實就是按照數(shù)據(jù)類型里的引用類型的概念去理解。
這一點與 CommonJS 規(guī)范完全不同。
CommonJS 模塊輸出的是值的緩存,不存在動態(tài)更新。
// module1.js export var foo = "bar"; setTimeout(() => foo = "baz", 500);
// module2.js import {foo} from "./module1.js" console.log(foo) setTimeout(() => console.log(foo), 1000); // console的結(jié)果 // bar // baz2.3.2 export可以出現(xiàn)在模塊內(nèi)的任何位置,但不能處于塊級作用域內(nèi)
// 報錯 { export let foo = "bar"; }2.3.3 import具有提升效果(類似于var),會提升到整個模塊的頭部,首先執(zhí)行
console.log(foo) import {foo} from "./script1.js"
參考資料:ECMAScript 6 入門
本文純屬原創(chuàng),為了方便大家理解,小故事,小栗子都是筆者自己想的。如果您覺得對你有幫助,麻煩給個贊,給作者灰暗的生活揮灑揮灑積極向上的正能量,謝謝啦^_^。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96770.html
摘要:在單核系統(tǒng)之上我們采用單進程單線程的模式來開發(fā)。由進程來管理所有的子進程,主進程不負(fù)責(zé)具體的任務(wù)處理,主要工作是負(fù)責(zé)調(diào)度和管理。模塊與模塊總結(jié)無論是模塊還是模塊,為了解決實例單線程運行,無法利用多核的問題而出現(xiàn)的。 前言 進程與線程是一個程序員的必知概念,面試經(jīng)常被問及,但是一些文章內(nèi)容只是講講理論知識,可能一些小伙伴并沒有真的理解,在實際開發(fā)中應(yīng)用也比較少。本篇文章除了介紹概念,通過...
摘要:忍者級別的函數(shù)操作對于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數(shù)是一個很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機制,如果...
摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會討論安全的類型檢測惰性載入函數(shù)凍結(jié)對象定時器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對寫代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...
摘要:的四種綁定規(guī)則的種綁定規(guī)則分別是默認(rèn)綁定隱式綁定顯示綁定綁定。綁定中的操作符,和其他語言中如的機制是不一樣的。規(guī)則例外在顯示綁定中,對于和的綁定將不會生效。它也是作為機制的一種替換,解決之前綁定過程各種規(guī)則帶來的復(fù)雜性。 徹底搞懂 JS 中 this 機制 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog 目錄 t...
摘要:圖數(shù)據(jù)類型圖引用類型深淺拷貝問題不知道什么是深拷貝和淺拷貝的請先去并在調(diào)試臺自己操作一下,這篇文章只會說明為何中會有這種問題。所以有的時候我們?yōu)榱吮苊鉁\拷貝,會用一些方式實現(xiàn)深拷貝。 首先要了解的js基礎(chǔ) 基本數(shù)據(jù)類型:Object、undefined、null、Boolean、Number、String、Symbol (ES6新加) Object包括: Array 、Date 、R...
閱讀 3752·2023-04-25 18:41
閱讀 1188·2021-11-11 16:55
閱讀 1844·2021-09-22 15:54
閱讀 3077·2021-09-22 15:51
閱讀 3554·2019-08-30 15:55
閱讀 1949·2019-08-30 14:19
閱讀 1294·2019-08-29 10:57
閱讀 1711·2019-08-29 10:56