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