摘要:依賴信息是一個(gè)數(shù)組,比如上面的依賴數(shù)組是源碼如下是利用正則解析依賴的一個(gè)函數(shù)時(shí)間出發(fā)函數(shù)主要看這個(gè)部分注釋是防止拷貝該時(shí)間的回調(diào)函數(shù),防止修改,困惑了一下。對(duì)的賦值需要同步執(zhí)行,不能放在回調(diào)函數(shù)里。
sea.js想解決的問題
惱人的命名沖突
煩瑣的文件依賴
對(duì)應(yīng)帶來(lái)的好處 Sea.js 帶來(lái)的兩大好處:通過 exports 暴露接口。這意味著不需要命名空間了,更不需要全局變量。這是一種徹底的命名沖突解決方案。
通過 require 引入依賴。這可以讓依賴內(nèi)置,開發(fā)者只需關(guān)心當(dāng)前模塊的依賴,其他事情 Sea.js 都會(huì)自動(dòng)處理好。對(duì)模塊開發(fā)者來(lái)說(shuō),這是一種很好的 關(guān)注度分離,能讓程序員更多地享受編碼的樂趣。
API速查1. seajs.config 2. seajs.use 3. define 4. require 5. require.async 6. exports 7. module.exportssea.js的執(zhí)行過程 啟動(dòng)
用script標(biāo)簽引入sea.js文件,seajs.config(data)啟動(dòng)配置函數(shù),config函數(shù)會(huì)會(huì)合并所有config配置,seajs.use = function(ids, callback),啟用主腳本
運(yùn)行過程主腳本啟動(dòng)之后,首先利用request模塊請(qǐng)求主腳本(生成script標(biāo)簽插入head標(biāo)簽中),然后根據(jù)正則解析模塊define的依賴,并對(duì)依賴遞歸解析其依賴。
在運(yùn)行過程中,通過監(jiān)聽發(fā)布者模式,系統(tǒng)內(nèi)置了8個(gè)事件,可用于開發(fā)插件。
resolve -- 將 id 解析成為 uri 時(shí)觸發(fā) load -- 開始加載文件時(shí)觸發(fā) fetch -- 具體獲取某個(gè) uri 時(shí)觸發(fā) request -- 發(fā)送請(qǐng)求時(shí)觸發(fā) define -- 執(zhí)行 define 方法時(shí)觸發(fā) exec -- 執(zhí)行 module.factory 時(shí)觸發(fā) config -- 調(diào)用 seajs.config 時(shí)觸發(fā) error -- 加載腳本文件出現(xiàn) 404 或其他錯(cuò)誤時(shí)觸發(fā)全局掛載
所有相關(guān)數(shù)據(jù)最后全部掛載在window.seajs下,包括方法及模塊數(shù)據(jù)。
小知識(shí)點(diǎn) exports與module.exportsexports 僅僅是 module.exports 的一個(gè)引用。在 factory 內(nèi)部給 exports 重新賦值時(shí),并不會(huì)改變 module.exports 的值。因此給 exports 賦值是無(wú)效的,不能用來(lái)更改模塊接口。
//源碼如下 // Exec factory var factory = mod.factory; var exports = isFunction(factory) ? factory.call(mod.exports = {}, require, mod.exports, mod) : factory關(guān)于動(dòng)態(tài)依賴
有時(shí)會(huì)希望可以使用 require 來(lái)進(jìn)行條件加載:
if (todayIsWeekend) require("play"); else require("work");
但請(qǐng)牢記,從靜態(tài)分析的角度來(lái)看,這個(gè)模塊同時(shí)依賴 play 和 work 兩個(gè)模塊,加載器會(huì)把這兩個(gè)模塊文件都下載下來(lái)。 這種情況下,推薦使用 require.async 來(lái)進(jìn)行條件加載。
//sea.js源碼如下 require.async = function(ids, callback) { //可傳入回調(diào)函數(shù) Module.use(ids, callback, uri + "_async_" + cid()) //——async_英語(yǔ)標(biāo)識(shí)這個(gè)腳本是異步加載的,cid用于清除緩存 return require //返回require方便鏈?zhǔn)秸{(diào)用 }在開發(fā)時(shí),Sea.js 是如何知道一個(gè)模塊的具體依賴呢?
a.js
define(function(require, exports) { var b = require("./b"); var c = require("./c"); });
Sea.js 在運(yùn)行 define 時(shí),接受 factory 參數(shù),可以通過 factory.toString() 拿到源碼,再通過正則匹配 require 的方式來(lái)得到依賴信息。依賴信息是一個(gè)數(shù)組,比如上面 a.js 的依賴數(shù)組是:["./b", "./c"]
//源碼如下 // Parse dependencies according to the module factory code if (!isArray(deps) && isFunction(factory)) { deps = typeof parseDependencies === "undefined" ? [] : parseDependencies(factory.toString()) //parseDependencies是利用正則解析依賴的一個(gè)函數(shù) }時(shí)間出發(fā)函數(shù)Emit
// Emit event, firing all bound callbacks. Callbacks receive the same // arguments as `emit` does, apart from the event name var emit = seajs.emit = function(name, data) { var list = events[name] if (list) { // Copy callback lists to prevent modification list = list.slice() // Execute event callbacks, use index because it"s the faster. for(var i = 0, len = list.length; i < len; i++) { list[i](data) } } return seajs }
主要看這個(gè)部分list = list.slice(),注釋是防止拷貝該時(shí)間的回調(diào)函數(shù),防止修改,困惑了一下。
原因是Javascript中賦值時(shí),對(duì)于引用數(shù)據(jù)類型,都是傳地址。
所以這里,如果想防止觸發(fā)事件的過程中回調(diào)函數(shù)被更改,必須對(duì)這個(gè)list數(shù)組進(jìn)行拷貝,而并非只是將list指向events[name]的地址。
// Remove the script to reduce memory leak if (!data.debug) { head.removeChild(node) }
這里思考了蠻久,為什么可以刪除動(dòng)態(tài)插入的腳本?這樣腳本還會(huì)生效嗎?
首先,必須了解計(jì)算機(jī)內(nèi)存分為
靜態(tài)數(shù)據(jù)區(qū) (用來(lái)存放程序中初始化的全局變量的一塊內(nèi)存區(qū)域)
代碼區(qū) (通常用來(lái)存放執(zhí)行代碼的一塊內(nèi)存區(qū)域)
棧區(qū) (棧在進(jìn)程運(yùn)行時(shí)產(chǎn)生,一個(gè)進(jìn)程有一個(gè)進(jìn)程棧。棧用來(lái)存儲(chǔ)程序臨時(shí)存放的局部變量,即函數(shù)內(nèi)定義的變量 不包括static 類型的。函數(shù)被調(diào)用時(shí),他的形參也會(huì)被壓棧。
堆區(qū) (用于存放進(jìn)程運(yùn)行中被動(dòng)態(tài)分配的內(nèi)存段,它的大小并且不固定,可動(dòng)態(tài)擴(kuò)展。當(dāng)進(jìn)程調(diào)用malloc等分配內(nèi)存時(shí),新分配的內(nèi)存被動(dòng)態(tài)的添加到堆上(堆被擴(kuò)大),當(dāng)利用free等函數(shù)釋放內(nèi)存時(shí),被釋放的‘ 內(nèi)存從堆中剔除)
這些在Javascript中都被屏蔽了,大部分時(shí)候我們都不需要考慮,但是如果要深入了解的話,則是必須要知道的知識(shí)。
首先HTML文檔中的JS腳本在計(jì)算機(jī)中作為指令被讀入內(nèi)存,之后開始執(zhí)行,CPU開始一條一條指令讀取,比如,讀取到var cool = "wilson"時(shí),就會(huì)在內(nèi)存中分配一個(gè)6字符大小的內(nèi)存,一個(gè)function也一樣會(huì)在內(nèi)存中占據(jù)一定大小。所以,當(dāng)指令全部運(yùn)行完之后,指令本身其實(shí)已經(jīng)沒有用了,但是仍然給占據(jù)了一部分內(nèi)存。
當(dāng)你點(diǎn)擊按鈕觸發(fā)一個(gè)回調(diào)函數(shù)時(shí),并非去讀取指令,而是讀取內(nèi)存中這個(gè)回調(diào)函數(shù)的地址。所以刪除這些動(dòng)態(tài)加載的JS文件是沒有問題的。
所謂 ID 和路徑匹配原則 是指,使用 seajs.use 或 require 進(jìn)行引用的文件,如果是具名模塊(即定義了 ID 的模塊),會(huì)把 ID 和 seajs.use 的路徑名進(jìn)行匹配,如果一致,則正確執(zhí)行模塊返回結(jié)果。反之,則返回 null。
對(duì) module.exports 的賦值需要同步執(zhí)行,不能放在回調(diào)函數(shù)里。下面這樣是不行的// x.js define(function(require, exports, module) { // 錯(cuò)誤用法 setTimeout(function() { module.exports = { a: "hello" }; }, 0); }); //在 y.js 里有調(diào)用到上面的 x.js: // y.js define(function(require, exports, module) { var x = require("./x"); // 無(wú)法立刻得到模塊 x 的屬性 a console.log(x.a); // undefined });
WilsonLiu"s blog首發(fā)地址:http://blog.wilsonliu.cn
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/79775.html
摘要:二模塊化規(guī)范概述應(yīng)用由模塊組成,采用模塊規(guī)范。模塊化語(yǔ)法命令用于規(guī)定模塊的對(duì)外接口,命令用于輸入其他模塊提供的功能。 前言 在JavaScript發(fā)展初期就是為了實(shí)現(xiàn)簡(jiǎn)單的頁(yè)面交互邏輯,寥寥數(shù)語(yǔ)即可;如今CPU、瀏覽器性能得到了極大的提升,很多頁(yè)面邏輯遷移到了客戶端(表單驗(yàn)證等),隨著web2.0時(shí)代的到來(lái),Ajax技術(shù)得到廣泛應(yīng)用,jQuery等前端庫(kù)層出不窮,前端代碼日益膨脹,此時(shí)...
摘要:二模塊化規(guī)范概述應(yīng)用由模塊組成,采用模塊規(guī)范。模塊化語(yǔ)法命令用于規(guī)定模塊的對(duì)外接口,命令用于輸入其他模塊提供的功能。 前言 在JavaScript發(fā)展初期就是為了實(shí)現(xiàn)簡(jiǎn)單的頁(yè)面交互邏輯,寥寥數(shù)語(yǔ)即可;如今CPU、瀏覽器性能得到了極大的提升,很多頁(yè)面邏輯遷移到了客戶端(表單驗(yàn)證等),隨著web2.0時(shí)代的到來(lái),Ajax技術(shù)得到廣泛應(yīng)用,jQuery等前端庫(kù)層出不窮,前端代碼日益膨脹,此時(shí)...
摘要:前端個(gè)靈魂拷問,徹底搞明白你就是中級(jí)前端工程師上篇感覺大家比較喜歡看這種類型的文章,以后會(huì)多一些。所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。此規(guī)范其實(shí)是在推廣過程中產(chǎn)生的。 showImg(https://segmentfault.com/img/bVbwAMU?w=700&h=394); 前端20個(gè)靈魂拷問,徹底搞明白你就是中級(jí)前端工程師...
摘要:前端個(gè)靈魂拷問,徹底搞明白你就是中級(jí)前端工程師上篇感覺大家比較喜歡看這種類型的文章,以后會(huì)多一些。所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。此規(guī)范其實(shí)是在推廣過程中產(chǎn)生的。 showImg(https://segmentfault.com/img/bVbwAMU?w=700&h=394); 前端20個(gè)靈魂拷問,徹底搞明白你就是中級(jí)前端工程師...
閱讀 774·2021-11-22 13:54
閱讀 3183·2021-09-26 10:16
閱讀 3606·2021-09-08 09:35
閱讀 1643·2019-08-30 15:55
閱讀 3488·2019-08-30 15:54
閱讀 2144·2019-08-30 10:57
閱讀 550·2019-08-29 16:25
閱讀 934·2019-08-29 16:15