RequiereJs學(xué)習(xí)筆記——RequireJS的由來和垃圾回收機(jī)制理解的閉包

Why?為什么要使用RequireJs?

一個程序員桥嗤,不管注釋寫的再好毯辅,總是會難以維護(hù)大型項目的代碼埂伦。100行沒問題,1000行沒問題思恐,3000行呢沾谜?5000行呢?那我光是瀏覽一遍都得花很多時間胀莹,極大的浪費了精力基跑。

那怎么辦呢?拆描焰。

把一個3000行的項目拆成幾百行幾百行的小項目(按組件)媳否。最傻的方式就是寫一個Scrip

/*topbar區(qū)域代碼*/
var $topbar=$('topbar')
//省略100行
$topbar.on('click',function(){
  console.log('topbar')
})
/*$banners區(qū)域代碼*/
var $banners=$('banners')
//省略100行
$banners.on('click',function(){
  console.log('topbar')
})
/*slides區(qū)域代碼*/
var $slides=('slides')
//省略100行
$slides.on('click',function(){
  console.log('topbar')
})

這樣就成功的把代碼分成了幾個部分。我們十分開心的把代碼們都隔開了荆秦,不會找錯修改的位置了篱竭。

但是這樣又產(chǎn)生了一個問題,如果哪個人手賤硬要在不同部分之間調(diào)用怎么辦呢步绸?我本來劃分的好好的不同段代碼又會變得雜亂無章掺逼,無法整理。

閉包問題:

于是有一個聰明的前端就想到了使用立即執(zhí)行函數(shù)來進(jìn)行隔離靡努,讓不同區(qū)域之間的代碼變成函數(shù)內(nèi)代碼坪圾,也就是把它做成局部變量放在函數(shù)里晓折。(順帶一提惑朦,ES6中兽泄,立即執(zhí)行函數(shù)是一句廢話,因為有l(wèi)et的存在漾月。)

function xxx(){

var $topbar =$('#topbar')

$topbar.on('click'),function(){

console.log('topbar')

}

出了函數(shù)作用域的塊病梢,$topbar就是Undefined,這樣就能做到消除全局變量了。

但是這樣又產(chǎn)生了一個問題梁肿,我們又重新把函數(shù)xxx()變成了全局變量蜓陌。這就很僵硬,我們并沒有消滅掉全局變量吩蔑,消滅掉一個又使用了一個钮热。

于是,又有一個聰明的前端想到了使用!function.

這么做的優(yōu)點是烛芬,我將無法越權(quán)修改模塊隧期。這就是立即執(zhí)行函數(shù)的意義,可以將環(huán)境分割開赘娄,讓各模塊之間不互相干擾仆潮。

然而寫著寫著突然發(fā)現(xiàn)了一個新需求:既然已經(jīng)隔開了,但是我現(xiàn)在想在其他模塊上做一個功能需要調(diào)用到這個作用域內(nèi)的函數(shù)遣臼,又怎么辦呢性置?

函數(shù)作用域是不可能互相訪問的,我們無法把作用域打通揍堰,但是我們可以做一個橋梁鹏浅。

每當(dāng)我們新生成一個作用域,它就相當(dāng)于一個孤島屏歹。

那么想讓兩個作用域交流怎么辦呢隐砸?

前端們自然就想到了在函數(shù)內(nèi)使用window.xxxyyy=xxxyyy,將函數(shù)內(nèi)的xxxyyy映射到window上西采,這樣全局不就都可以訪問了嗎凰萨?真是機(jī)智。

但是這樣就又發(fā)生了一個問題械馆,我們將username映射到了全局胖眷。如果一個不小心誤修改啥的怎么辦呢?還是不妥。

我們需要的是什么霹崎?是讓username只能讀珊搀,不能寫。

于是:

window.userGetter={

nameGetter:function(){

return user.name

},

ageGetter:function(){

return user.age

}

}

我們使用了一次閉包尾菇,將這個問題解決了境析。別的作用域只能讀取user,不能改user.

閉包在哪囚枪?

在這里說說我的理解。

閉包的用途就是如上:有一個獨立的作用域劳淆,可以通過全局變量直接將內(nèi)部的變量映射出去链沼。但是我暴露出去就會有一定的風(fēng)險,容易被人修改沛鸵,于是我就不暴露一個變量括勺,而是暴露一個函數(shù)。這個函數(shù)可以修改這個變量曲掰,但是只做有限的操作疾捍。外部調(diào)取只知道函數(shù)名而去訪問它,不知道實際上自己操作的是哪個變量名栏妖,從而對變量的值進(jìn)行保護(hù)乱豆,閉包就是一種作用域的特殊使用方式。

如果要個人做一個定義:

閉包:如果一個函數(shù)吊趾,它的內(nèi)部使用了它外部的變量宛裕,那么這個函數(shù)和這個變量就組合成了一個閉包。

而閉包的作用機(jī)制趾徽,我認(rèn)為用JS的垃圾回收機(jī)制來說明可能比較清晰明了续滋。

如果我定義一個函數(shù)a,并在函數(shù)a內(nèi)寫了return b.

然后定義并調(diào)用 var fb=a();

那么fb,就是return b 閉包函數(shù)的引用孵奶。在我執(zhí)行var fb后疲酌,調(diào)用了a(),作用域鏈為函數(shù)b→a()→window.

fb會依次往上尋找,直到找到變量為止(找不到則為undefined)

JS垃圾回收機(jī)制是不引用則銷毀了袁,而這里我們可以看到朗恳,作用域鏈中a()被fb引用,而b被a()引用载绿,也就是說只要fb的引用存在粥诫,那么b就一直不會被銷毀。

順便一提崭庸,方法訪問變量怀浆,變量存在內(nèi)存中,這樣做應(yīng)該會讓內(nèi)存使用的更多才對怕享。

——————————————————————————————————————————————

回到正題执赡。這么使用似乎已經(jīng)解決了所有問題。但是很快的函筋,會搞事的前端又覺得不爽了沙合。

代碼根本沒有關(guān)聯(lián),為啥要放在一個文件里跌帐?太sb了首懈。分開吧绊率。

于是:

拆成topbar.js,slide.js,banner.js,他們之間根本無法互相影響。完美究履!簡單粗暴的模塊化B朔瘛!搞那么多彎彎繞繞干嘛?嫱唷M缒簟肥惭!還不如一個切圖仔想的辦法好6⒁恰!蜜葱!

前端工程師:你呀全景,畢竟Naive.

那我有些功能寫了一遍并不想再寫一遍,比如topbar和banner有相近似的功能牵囤,我就是想用他們之中共通的部分爸黄,又怎么辦呢?寫個插件吧。頭疼的事又來了揭鳞,他們之間沒法互相訪問翱还蟆!我寫了也沒法在其他JS文件中調(diào)用野崇。你這樣模塊化是不是略僵硬了称开?比如:

new Plugin({element:'#banners>slides.js.'})

寫了這個插件之后,我就只能先調(diào)用plugin而不能調(diào)用別的了乓梨。順序固定了鳖轰。

而我們知道,兩個局部作用域扶镀,如果沒有window蕴侣,是永遠(yuǎn)無法調(diào)用其他部分的。

但是分JS文件后臭觉,我這么做都是白費功夫昆雀,一旦我要依賴,還是要暴露到全局蝠筑。

暴露到全局的變量太多狞膘,太煩了。于是聰明的前端先做一個window.app={}菱肖,然后將所有東西都掛載在window.app里客冈。那么我所有的調(diào)用都是調(diào)用app里的,只使用了一個全局變量稳强。是不是跨時代的做法3≈佟:驮谩(旁人:兄弟,你這不是騙自己嗎...該暴露的一個沒少扒啤)

而這個方案鸽素,在前端維持了很長一段時間。最著名的庫就是:

Jquery($符號)亦鳞、YUI等馍忽。他們都是這么做的

直到requireJs的出現(xiàn)。

Jquery的做法是:分割變量不就是需要立即執(zhí)行函數(shù)嗎燕差,那傳給我遭笋,我?guī)湍銏?zhí)行。上面的需求如果用JQ做徒探,那么我把它掛載在JQ上:

var Plugin=$.Plugin

然后再從$上去取我要的函數(shù)瓦呼。而這種方式,我們叫做命名空間(所有命名都是以同一個空間作為掛載)

requireJS:我覺得你這個方法不錯测暗,那我....我就把命名空間的名字固定一下吧央串。(騙star嗎兄弟!M胱摹)

window.require(['./plugin.js'],function(Plugin ))

接著就只需要寫main.js了质和,main.js聲明了自己依賴了三個js,分別為A\B\C.

ABC里進(jìn)行了分類,聲明了依賴的順序稚字,全部加載完后就會執(zhí)行main.js

QQ圖片20170613134855
QQ圖片20170613134855

于是RequireJS就成為了一個很棒棒的庫饲宿,一直到了今天.....

嗯,接下來就是學(xué)習(xí)如何使用了尉共,這個坑慢慢填褒傅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袄友,隨后出現(xiàn)的幾起案子殿托,更是在濱河造成了極大的恐慌,老刑警劉巖剧蚣,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件支竹,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸠按,警方通過查閱死者的電腦和手機(jī)礼搁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來目尖,“玉大人馒吴,你說我怎么就攤上這事。” “怎么了饮戳?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵豪治,是天一觀的道長。 經(jīng)常有香客問我扯罐,道長负拟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任歹河,我火速辦了婚禮掩浙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秸歧。我一直安慰自己厨姚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布寥茫。 她就那樣靜靜地躺著遣蚀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纱耻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天险耀,我揣著相機(jī)與錄音弄喘,去河邊找鬼。 笑死甩牺,一個胖子當(dāng)著我的面吹牛蘑志,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贬派,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼急但,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搞乏?” 一聲冷哼從身側(cè)響起波桩,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎请敦,沒想到半個月后镐躲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡侍筛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年萤皂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匣椰。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡裆熙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情入录,我是刑警寧澤齐媒,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站纷跛,受9級特大地震影響喻括,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贫奠,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一唬血、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦丸逸、人聲如沸书蚪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至芦疏,卻和暖如春冕杠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酸茴。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工分预, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人薪捍。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓笼痹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酪穿。 傳聞我的和親對象是個殘疾皇子凳干,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容