Underscore.js常用方法介绍
Underscore.js是一個(gè)很精干的庫(kù),壓縮后只有4KB。它提供了幾十種函數(shù)式編程的方法,彌補(bǔ)了標(biāo)準(zhǔn)庫(kù)的不足,大大方便了JavaScript的編程。MVC框架Backbone.js就將這個(gè)庫(kù)作為自己的工具庫(kù)。除了可以在瀏覽器環(huán)境使用,Underscore.js還可以用于Node.js。
Underscor.js定義了一個(gè)下劃線(_)對(duì)象,函數(shù)庫(kù)的所有方法都屬于這個(gè)對(duì)象。這些方法大致上可以分成:集合(collection)、數(shù)組(array)、函數(shù)(function)、對(duì)象(object)和工具(utility)五大類。
這里介紹部分的常用方法,詳細(xì)請(qǐng)API文檔?http://www.css88.com/doc/underscore/
從API中,你已經(jīng)可以看出,Underscore沒(méi)有任何復(fù)雜的結(jié)構(gòu)和流程,它僅僅提供了一系列常用的函數(shù)。如果你將API中的方法從頭至尾用一遍,你就會(huì)對(duì)它非常了解。盡管如此,但我覺(jué)得還是有必要將一些重要的方法拿出來(lái)與大家討論,它們十分重要,卻在API中描述地還不夠清楚。
1 Underscore對(duì)象封裝
Underscore并沒(méi)有在原生的JavaScript對(duì)象原型中進(jìn)行擴(kuò)展,而是像jQuery一樣,將數(shù)據(jù)封裝在一個(gè)自定義對(duì)象中(下文中稱“Underscore對(duì)象”)。
你可以通過(guò)調(diào)用一個(gè)Underscore對(duì)象的value()方法來(lái)獲取原生的JavaScript數(shù)據(jù),例如:
javascript 代碼:2 優(yōu)先調(diào)用JavaScript 1.6內(nèi)置方法
Underscore中有許多方法在JavaScript1.6中已經(jīng)被納入規(guī)范,因此在Underscore對(duì)象內(nèi)部,會(huì)優(yōu)先調(diào)用宿主環(huán)境提供的內(nèi)置方法(如果宿主環(huán)境已經(jīng)實(shí)現(xiàn)了這些方法),以此提高函數(shù)的執(zhí)行效率。
而對(duì)于不支持JavaScript 1.6的宿主環(huán)境,Underscore會(huì)通過(guò)自己的方式實(shí)現(xiàn),而對(duì)開(kāi)發(fā)者來(lái)說(shuō),這些完全是透明的。
這里所說(shuō)的宿主環(huán)境,可能是Node.js運(yùn)行環(huán)境,或客戶端瀏覽器。
3 改變命名空間
Underscore默認(rèn)使用_(下劃線)來(lái)訪問(wèn)和創(chuàng)建對(duì)象,但這個(gè)名字可能不符合我們的命名規(guī)范,或容易引起命名沖突。
我們可以通過(guò)noConflict()方法來(lái)改變Underscore的命名,并恢復(fù)_(下劃線)變量之前的值,例如:
html 代碼:4 鏈?zhǔn)讲僮?/h2>
還記得我們?cè)趈Query中是如何進(jìn)行鏈接操作嗎?例如:
javascript 代碼:Underscore同樣支持鏈?zhǔn)讲僮?#xff0c;但你需要先調(diào)用chain()方法進(jìn)行聲明:
javascript 代碼:如果調(diào)用了chain()方法,Underscore會(huì)將所調(diào)用的方法封裝在一個(gè)閉包內(nèi),并將返回值封裝為一個(gè)Underscore對(duì)象并返回:
javascript 代碼:?
5 擴(kuò)展Underscore
我們可以通過(guò)mixin()方法輕松地向Underscore中擴(kuò)展自定義方法,例如:
javascript 代碼:這些方法被追加到Underscore的原型對(duì)象中,所有創(chuàng)建的Underscore對(duì)象都可以使用這些方法,它們享有和其它方法同樣的環(huán)境。
6 遍歷集合
each()和map()方法是最常用用到的兩個(gè)方法,它們用于迭代一個(gè)集合(數(shù)組或?qū)ο?#xff09;,并依次處理集合中的每一個(gè)元素,例如:
javascript 代碼:map()方法與each()方法的作用、參數(shù)相同,但它會(huì)將每次迭代函數(shù)返回的結(jié)果記錄到一個(gè)新的數(shù)組并返回。
7 函數(shù)節(jié)流
函數(shù)節(jié)流是指控制一個(gè)函數(shù)的執(zhí)行頻率或間隔(就像控制水流的閘門一樣),Underscore提供了debounce()和throttle()兩個(gè)方法用于函數(shù)節(jié)流。
為了更清楚地描述這兩個(gè)方法,假設(shè)我們需要實(shí)現(xiàn)兩個(gè)需求:
需求1:當(dāng)用戶在文本框輸入搜索條件時(shí),自動(dòng)查詢匹配的關(guān)鍵字并提示給用戶(就像在Tmall輸入搜索關(guān)鍵字時(shí)那樣)
首先分析第1個(gè)需求,我們可以綁定文本框的keypress事件,當(dāng)輸入框內(nèi)容發(fā)生變化時(shí),查詢匹配關(guān)鍵字并展示。假設(shè)我想查詢“windows phone”,它包含13個(gè)字符,而我輸入完成只花了1秒鐘(好像有點(diǎn)快,就意思意思吧),那么在這1秒內(nèi),調(diào)用了13次查詢方法。這是一件非常恐怖的事情,如果Tmall也這樣實(shí)現(xiàn),我擔(dān)心它會(huì)不會(huì)在光棍節(jié)到來(lái)之前就掛掉了(當(dāng)然,它并沒(méi)有這么脆弱,但這絕對(duì)不是最好的方案)
更好的方法是,我們希望用戶已經(jīng)輸入完成,或者正在等待提示(也許他懶得再輸入后面的內(nèi)容)的時(shí)候,再查詢匹配關(guān)鍵字。
最后我們發(fā)現(xiàn),在我們期望的這兩種情況下,用戶會(huì)暫時(shí)停止輸入,于是我們決定在用戶暫停輸入200毫秒后再進(jìn)行查詢(如果用戶在不斷地輸入內(nèi)容,那么我們認(rèn)為他可能很明確自己想要的關(guān)鍵字,所以等一等再提示他)
這時(shí),利用Underscore中的debounce()函數(shù),我們可以輕松實(shí)現(xiàn)這個(gè)需求:
html 代碼:你能看到,我們的代碼非常簡(jiǎn)潔,節(jié)流控制在debounce()方法中已經(jīng)被實(shí)現(xiàn),我們只告訴它當(dāng)query函數(shù)在200毫秒內(nèi)沒(méi)有被調(diào)用過(guò)的話,就執(zhí)行我們的查詢操作,然后再將query函數(shù)綁定到輸入框的keypress事件。
query函數(shù)是怎么來(lái)的?我們?cè)谡{(diào)用debounce()方法時(shí),會(huì)傳遞一個(gè)執(zhí)行查詢操作的函數(shù)和一個(gè)時(shí)間(毫秒數(shù)),debounce()方法會(huì)根據(jù)我們傳遞的時(shí)間對(duì)函數(shù)進(jìn)行節(jié)流控制,并返回一個(gè)新的函數(shù)(即query函數(shù)),我們可以放心大膽地調(diào)用query函數(shù),而debounce()方法會(huì)按要求幫我們做好控制。
需求2:當(dāng)用戶拖動(dòng)瀏覽器滾動(dòng)條時(shí),調(diào)用服務(wù)器接口檢查是否有新的內(nèi)容
再來(lái)分析第2個(gè)需求,我們可以將查詢方法綁定到window.onscroll事件,但這顯然不是一個(gè)好的做法,因?yàn)橛脩敉蟿?dòng)一次滾動(dòng)條可能會(huì)觸發(fā)幾十次甚至上百次onscroll事件。
我們是否可以使用上面的debounce()方法來(lái)進(jìn)行節(jié)流控制?當(dāng)用戶拖動(dòng)滾動(dòng)條完畢后,再查詢新的內(nèi)容?但這與需求不符,用戶希望在拖動(dòng)的過(guò)程中也能看到新內(nèi)容的變化。
因此我們決定這樣做:用戶在拖動(dòng)時(shí),每?jī)纱尾樵兊拈g隔不少于500毫秒,如果用戶拖動(dòng)了1秒鐘,這可能會(huì)觸發(fā)200次onscroll事件,但我們最多只進(jìn)行2次查詢。
利用Underscore中的throttle()方法,我們也可以輕松實(shí)現(xiàn)這個(gè)需求:
html 代碼:代碼仍然十分簡(jiǎn)潔,因?yàn)樵趖hrottle()方法內(nèi)部,已經(jīng)為我們實(shí)現(xiàn)的所有控制。
你可能已經(jīng)發(fā)現(xiàn),debounce()和throttle()兩個(gè)方法非常相似(包括調(diào)用方式和返回值),作用卻又有不同。
它們都是用于函數(shù)節(jié)流,控制函數(shù)不被頻繁地調(diào)用,節(jié)省客戶端及服務(wù)器資源。
- debounce()方法關(guān)注函數(shù)執(zhí)行的間隔,即函數(shù)兩次的調(diào)用時(shí)間不能小于指定時(shí)間。
- throttle()方法更關(guān)注函數(shù)的執(zhí)行頻率,即在指定頻率內(nèi)函數(shù)只會(huì)被調(diào)用一次。
?
5.8 模板解析
Underscore提供了一個(gè)輕量級(jí)的模板解析函數(shù),它可以幫助我們有效地組織頁(yè)面結(jié)構(gòu)和邏輯。
我將通過(guò)一個(gè)例子來(lái)介紹它:
html 代碼:在本例中,我們將模板內(nèi)容放到一個(gè)<script>標(biāo)簽中,你可能已經(jīng)注意到標(biāo)簽的type是text/template而不是text/javascript,因?yàn)樗鼰o(wú)法作為JavaScript腳本直接運(yùn)行。
我也建議你將模板內(nèi)容放在<script>中,因?yàn)槿绻銓⑺鼈儗?xiě)在一個(gè)<div>或其它標(biāo)簽中,它們可能會(huì)被添加到DOM樹(shù)中進(jìn)行解析(即使你隱藏了這個(gè)標(biāo)簽也無(wú)法避免)。
?
_.template模板函數(shù)只能解析3種模板標(biāo)簽(這比Smarty、JSTL要簡(jiǎn)單得多):
<% ?%>:用于包含JavaScript代碼,這些代碼將在渲染數(shù)據(jù)時(shí)被執(zhí)行。
<%= %>:用于輸出數(shù)據(jù),可以是一個(gè)變量、某個(gè)對(duì)象的屬性、或函數(shù)調(diào)用(將輸出函數(shù)的返回值)。
<%- %>:用于輸出數(shù)據(jù),同時(shí)會(huì)將數(shù)據(jù)中包含的HTML字符轉(zhuǎn)換為實(shí)體形式(例如它會(huì)將雙引號(hào)轉(zhuǎn)換為"形式),用于避免XSS攻擊。
當(dāng)我們希望將數(shù)據(jù)中的HTML作為文本顯示出來(lái)時(shí),常常會(huì)使用<%- %>標(biāo)簽。
Underscore還允許你修改這3種標(biāo)簽的形式,如果我們想使用{% %}、{%= %}、{%- %}作為標(biāo)簽,可以通過(guò)修改templateSettings來(lái)實(shí)現(xiàn),就像這樣:
javascript 代碼:在本例中,我們將模板內(nèi)容和需要填充的數(shù)據(jù)傳遞給template方法,它會(huì)按以下順序進(jìn)行處理:
- 將模板內(nèi)容解析為可執(zhí)行的JavaScript(解析模板標(biāo)簽)
- 通過(guò)with語(yǔ)句將解析后的JavaScript作用域修改為我們傳遞的數(shù)據(jù)對(duì)象,這使我們能夠直接在模板中通過(guò)變量形式訪問(wèn)數(shù)據(jù)對(duì)象的屬性
- 執(zhí)行解析后的JavaScript(將數(shù)據(jù)填充到模板)
- 返回執(zhí)行后的結(jié)果
我們經(jīng)常會(huì)遇到一種情況:多次調(diào)用template方法將數(shù)據(jù)渲染到同一個(gè)模板。
假設(shè)我們有一個(gè)分頁(yè)列表,列表中的每一條數(shù)據(jù)都通過(guò)模板渲染,當(dāng)用戶進(jìn)入下一頁(yè),我們會(huì)獲取下一頁(yè)的數(shù)據(jù)并重新渲染,實(shí)際上每次渲染的模板都是同一個(gè),但剛才描述的template所有處理過(guò)程總會(huì)被執(zhí)行。
其實(shí)Underscore的template方法提供了一種更高效的調(diào)用方式,我們將上面代碼中的最后兩句修改為:
javascript 代碼:你會(huì)發(fā)現(xiàn)細(xì)微的差別:我們?cè)谡{(diào)用template方法時(shí)只傳遞了模板內(nèi)容,而沒(méi)有傳遞數(shù)據(jù),此時(shí)template方法會(huì)解析模板內(nèi)容,生成解析后的可執(zhí)行JavaScript代碼,并返回一個(gè)函數(shù),而函數(shù)體就是解析后的JavaScript,因此當(dāng)我們調(diào)用該函數(shù)渲染數(shù)據(jù)時(shí),就省去了模板解析的動(dòng)作。
你應(yīng)該將返回的函數(shù)存儲(chǔ)起來(lái)(就像我將它存儲(chǔ)在render變量中一樣),再通過(guò)調(diào)用該函數(shù)來(lái)渲染數(shù)據(jù),特別是在同一個(gè)模板可能會(huì)被多次渲染的情況下,這樣做能提高執(zhí)行效率(具體提升多少,應(yīng)該根據(jù)你的模板長(zhǎng)度和復(fù)雜度而定,但無(wú)論如何,這都是一個(gè)良好的習(xí)慣)。
總結(jié)
以上是生活随笔為你收集整理的Underscore.js常用方法介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 小白十分钟-推荐导航栏
- 下一篇: 掌握ES6/ES2015核心内容