underscore.js庫的淺析

Underscore並無在原生的JavaScript對象原型中進行擴展,而是像jQuery同樣,將數據封裝在一個自定義對象中(下文稱「Underscore對象」)。生成一個Underscore對象:javascript

<script>html

  var jsData = {
      name : 'data'
  }
    // 經過_()方法將對象建立爲一個Underscore對象
  var underscoreData = _(jsData);   //_就是Underscore構造函數的標識java

    // underscoreData對象的原型中包含了Underscore中定義的全部方法,你能夠任意使用
   
  underscoreData.value();ajax

    // 經過value方法獲取原生數據, 即jsDatajson

</script>數組

Underscore默認使用_(下劃線)來訪問和建立對象,但這個名字可能不符合咱們的命名規範,或容易引發命名衝突。咱們能夠經過noConflict()方法來改變Underscore的命名,並恢復_(下劃線)變量以前的值,例如:服務器

<script type="text/javascript">
    var _ = '自定義變量';
</script>
<script type="text/javascript"  src="http://handyxuefeng.blog.163.com/blog/underscore/underscore-min.js"></script>
<script type="text/javascript">
     
    console.log(_);  // Underscore對象
     
    var us = _.noConflict();  // 將Underscore對象重命名爲us, 後面都經過us來訪問和建立Underscore對象
    
    console.log(_);    // 輸出"自定義變量"
</script>函數

Underscore一樣支持鏈式操做,但你須要先調用chain()方法進行聲明。this

var arr = [10, 20, 30];
_(arr)         //新建一個Underscore對象
    .chain()    //聲明我要鏈式操做了
    .map(function(item){ return item++; })
    .first()
    .value();spa

咱們能夠經過mixin()方法輕鬆地向Underscore中擴展自定義方法,例如:

_.mixin({
    method1: function(object) {
        // to do
    },
    method2: function(arr) {
        // to do
    },
    method3: function(fn) {
        // to do
    }
}); 

 這些方法被追加到Underscore的原型對象中,全部建立的Underscore對象均可以使用這些方法,它們享有和其它方法一樣的環境。

Underscore提供了一個輕量級的模板解析函數,它能夠幫助咱們有效地組織頁面結構和邏輯。handlebars也是作這個處理的。若是是簡單的模板解析,Backbone裏面有自帶的方法,它使用的就是Underscore中的方法。handlebars處理更復雜的模板解析。舉例:


<ul id="element"></ul>     //用於顯示渲染後的標籤

<script type="text/template" id="tpl">     //定義模板,將模板內容放到一個script標籤中
    <% for(var i = 0; i < list.length; i++) { %>
        <% var item = list[i] %>
        <li>
            <span><%=item.firstName%> <%=item.lastName%></span>
            <span><%-item.city%></span>
        </li>
    <% } %>
</script>
<script type="text/javascript" src="http://handyxuefeng.blog.163.com/blog/underscore/underscore-min.js"></script>
<script type="text/javascript">
     
    var element = $('#element'),// 獲取渲染元素和模板內容
        tpl = $('#tpl').html();

    // 建立數據, 這些數據多是你從服務器獲取的
    var data = {
        list: [
            {firstName: '<a href="http://handyxuefeng.blog.163.com/blog/#">Zhang</a>', lastName: 'San', city: 'Shanghai'},
            {firstName: 'Li', lastName: 'Si', city: '<a href="http://handyxuefeng.blog.163.com/blog/#">Beijing</a>'},
            {firstName: 'Wang', lastName: 'Wu', city: 'Guangzhou'},
            {firstName: 'Zhao', lastName: 'Liu', city: 'Shenzhen'}
        ]
    }
    // 解析模板, 返回解析後的內容
    var html = _.template(tpl, data);      //把json數據解析到模板中去,並生成html字符串。
     
    element.html(html);  // 將解析後的內容填充到渲染元素
</script> 

  • 在本例中,咱們將模板內容放到一個<script>標籤中,你可能已經注意到標籤的type是text/template而不是text/javascript,由於它沒法做爲JavaScript腳本直接運行。
  • 我也建議你將模板內容放在<script>中,由於若是你將它們寫在一個<div>或其它標籤中,它們可能會被添加到DOM樹中進行解析(即便你隱藏了這個標籤也沒法避免)。
  • _.template模板函數只能解析3種模板標籤:
  • <%  %>:用於包含JavaScript代碼,這些代碼將在渲染數據時被執行。
  • <%= %>:用於輸出數據,能夠是一個變量、某個對象的屬性、或函數調用(將輸出函數的返回值)。
  • <%- %>:用於輸出數據,同時會將數據中包含的HTML字符轉換爲實體形式(例如它會將雙引號轉換爲&quot;形式),用於避免XSS攻擊。
  • 咱們常常會遇到一種狀況:屢次調用template方法將數據渲染到同一個模板。
  • 假設咱們有一個分頁列表,列表中的每一條數據都經過模板渲染,當用戶進入下一頁,咱們會獲取下一頁的數據並從新渲染,實際上每次渲染的模板都是同一個,但剛纔描述的template全部處理過程總會被執行。
  • 其實Underscore的template方法提供了一種更高效的調用方式,咱們將上面代碼中的最後兩句修改成:
  • var render = _.template(tpl);     // 解析模板, 返回解析後的內容
    var html = render(data);    //填充數據
    element.html(html);  // 將解析後的內容填充到渲染元素
  • 你會發現細微的差異:咱們在調用template方法時只傳遞了模板內容,而沒有傳遞數據,此時template方法會解析模板內容,生成解析後的可執行JavaScript代碼,並返回一個函數,而函數體就是解析後的 JavaScript,所以當咱們調用該函數渲染數據時,就省去了模板解析的動做。
  • 將模板內容解析爲可執行的JavaScript(解析模板標籤)
  • 經過with語句將解析後的JavaScript做用域修改成咱們傳遞的數據對象,這使咱們可以直接在模板中經過變量形式訪問數據對象的屬性
  • 執行解析後的JavaScript(將數據填充到模板)
  • 返回執行後的結果
  • if,else語句,不須要添加大括號{}。

最後,講幾個underscore中的方法:

  map()方法與each()方法的做用、參數相同,但它會將每次迭代函數返回的結果記錄到一個新的數組並返回。

  map方法在原生的js中是存在的,each方法是重寫了原生js的forEach方法,請看博客:http://www.cnblogs.com/chaojidan/p/4142338.html

  debounce()方法關注函數執行的間隔,即函數兩次的調用時間不能小於指定時間。

  throttle()方法更關注函數的執行頻率,即在指定頻率內函數只會被調用一次。

debounce

形像的比喻是橡皮球。若是手指按住橡皮球不放,它就一直受力,不能反彈起來,直到鬆手。

debounce 的關注點是空閒的間隔時間。

// ajaxQuery 將在中止輸入 250 毫秒後執行,若是用戶一直輸入(空閒的間隔時間小於250ms),那麼將不會執行ajaxQuery 。

$('#autocomplete').addEventListener('keyup',debounce(250,function() { ajaxQuery(this.value,renderUI); },true))

主要的應用場景:文本輸入keydown 事件,keyup 事件,例如作autocomplete。

throttle

形像的比喻是水龍頭或機槍,你能夠控制它的流量或頻率。

throttle 的關注點是連續的執行間隔時間。

// 當窗口大小改變時,以 50 毫秒一次的頻率爲單位執行定位函數 position。由於用戶在拖動窗口時,會觸發無數個resize事件,若是不作節流,它會執行無數次回調方法。所以使用節流方法,使每隔50毫秒(間隔時間),才執行回調方法。

window.addEventListener('resize',throttle(50,position,true) );

主要應用場景:window對象的resize和scroll 事件,mousemove鼠標移動事件

 

 

 

加油!

相關文章
相關標籤/搜索