Zepto源碼之工具函數

$.each

遍歷數組元素或以key-value值對方式遍歷對象。回調函數返回 false 時停止遍歷。

關於爲什麼使用它,而不使用原生的 forEach 方法,我的看法是 .eachindex,elementforEachelement,index,arr使 .each 方法進行遍歷操作更加的安全,而不用擔心修改了數組。如果需要修改數組,那麼可以使用 $.map 方法來遍歷創建一個新數組。這樣還保證了數據的安全性。


$.each = function (elements, callback) {
    var i, key
    // 如果是一個類數組的形式,那麼就以數組的形式遍歷
    if (likeArray(elements)) {
      for (i = 0; i < elements.length; i++)
        // 通過 call 形式調用,callback 函數,傳入的參數是元素位置
        // 與元素本身,如果回調返回 false 時,那麼停止遍歷
        if (callback.call(elements[i], i, elements[i]) === false) return elements
    } else {
      // 如果不是一個類數組,那麼就用對象的形式遍歷
      for (key in elements)
        // 通過 call 形式調用,callback 函數,傳入的參數是元素位置
        // 與元素本身,如果回調返回 false 時,那麼停止遍歷
        if (callback.call(elements[key], key, elements[key]) === false) return elements
    }
    return elements
  }

$.map

通過遍歷集合中的元素,返回通過迭代函數的全部結果(注:是一個新數組,從而保證了原數組的數據安全性),null 和 undefined 將被過濾掉。


$.map = function (elements, callback) {
    var value, values = [], i, key
    // 如果是一個類數組的形式,那麼就以數組的形式遍歷
    if (likeArray(elements))
      for (i = 0; i < elements.length; i++) {
        // 調用 callback ,傳入參數是 元素與元素位置,返回值賦值給value
        // 如果 value 不爲 null 或者 undefined 那麼 將 value 的值 push 到 values 中
        // PS:說句題外話,這個代碼風格值得一噴
        // 如果按照 $.each 的寫法,那麼回調的調用方式應該是 callback.call(elements[i], elements[i], i)
        value = callback(elements[i], i)
        if (value != null) values.push(value)
      }
    else
      // 如果不是一個類數組,那麼就用對象的形式遍歷
      for (key in elements) {
        value = callback(elements[key], key)
        if (value != null) values.push(value)
      }
    // 將 values 數組展開並返回(差不多有點有則改之,無則加勉的意思)
    return flatten(values)
  }

關於 flatten函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.trim

除去字符串左右空格,如果是 null 或者 undefined 那麼返回空串,否則調用字符串原生trim方法。

因爲zepto主要是爲移動端設計的,所以通常使用的是webkit內核,所以不用考慮 IE8 不兼容 trim 而要自己寫 trim 函數。直接調用即可。

$.trim = function (str) {
    return str == null ? "" : String.prototype.trim.call(str)
  }

// 在一般兼容IE8的項目中,我們可以拓展String原型,不過這是題外話
String.prototype.trim = function(){
    this.replace(/(^+)|(+$)/g,'')
}

$.parseJSON

格式化JSON。

直接調用瀏覽器方法。

if (window.JSON) $.parseJSON = JSON.parse

$.contains

檢查父節點是否包含給定的dom節點,如果兩者是相同的節點,則返回 false。

先檢查瀏覽器是否包含 contains 方法。如果包含的話,那麼直接調用該方法。否則使用自己編寫的 polyfill 方法。

$.contains = document.documentElement.contains ?
    function (parent, node) {
    // 直接判斷兩個元素是否是同一個元素,然後再直接調用元素方法查看 node 是不是 parent 的子孫元素
      return parent !== node && parent.contains(node)
    } :
    function (parent, node) {
      // 當 node 存在,且 node 存在父元素的時候,把 node 的父元素賦值給 node 
      // 然後對比 node 是不是與傳入的 parent相等,如果相等那麼說明 node 是 parent 的 子元素。如果不等那麼循環操作,一直對比到 html 元素爲止。
      // 這樣如果有相等就可以判斷 parent 是 node 的祖先元素。
      // 如果一直找不到的話,那就說明 parent 中不包含 node。 那麼返回 false
      while (node && (node = node.parentNode))
        if (node === parent) return true
      return false
    }

$.type

獲取JavaScript 對象的類型。可能的類型有: null undefined boolean number string function array date regexp object error。


$.type = type

關於 type 函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.isFunction

如果object是function,則返回ture。


$.isFunction = isFunction

關於 isFunction函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.isWindow

如果object參數爲一個window對象,那麼返回true。這在處理iframe時非常有用,因爲每個iframe都有它們自己的window對象,使用常規方法obj === window校驗這些objects的時候會失敗。


$.isWindow = isWindow

關於 isWindow函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.isArray

如果object是array,則返回ture。


$.isArray = isArray

關於 isArray函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.isPlainObject

測試對象是否是“純粹”的對象,這個對象是通過 對象常量(”{}”) 或者 new Object 創建的,如果是,則返回true。


$.isPlainObject = isPlainObject

關於 isPlainObject函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.isEmptyObject


$.isEmptyObject = function (obj) {
    var name
    // 如果使用 for..in 循環能遍歷出屬性那麼說明,參數有屬性,即非空對象,那麼返回 false 否則返回 true
    for (name in obj) return false
    return true
  }

$.isNumeric

如果該值爲有限數值或一個字符串表示的數字,則返回ture。


$.isNumeric = function (val) {
    // 先將 val 轉化成一個 Number 對象,再檢查 val 的類型
    // null undefined 肯定非數字,返回 false
    // boolean 的值只有 false ,true 肯定非數字,返回false
    // 不是字符串類型,但是有length屬性,那麼說明是類數組或者數組,肯定非數字,返回false
    // 通過 isNaN ,isFinite 檢測,那麼說明它是一個數字,返回false
    // 沒如果不能通過上述的所有條件,那麼肯定不是一個數字,返回false
    var num = Number(val), type = typeof val
    return val != null && type != 'boolean' &&
      (type != 'string' || val.length) &&
      !isNaN(num) && isFinite(num) || false
  }

$.noop

引用一個空函數(什麼都不處理)。


$.noop = function () { }

$.inArray

返回數組中指定元素的索引值,如果沒有找到該元素則返回-1。


$.inArray = function (elem, array, i) {
    return emptyArray.indexOf.call(array, elem, i)
  }

// 題外話
// 在ES6版本中,我們已經可以使用 Array.indexOf() 來檢測元素位置
// 在ES7中我們可以使用 Array.includes() 來檢測元素是否存在於數組中

$.camelCase

將一組字符串變成“駱駝”命名法的新字符串,如果該字符已經是“駱駝”命名法,則不變化。


$.camelCase = camelize

關於 camelize函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀

$.grep

獲取一個新數組,新數組只包含回調函數中返回 ture 的數組項。


$.grep = function (elements, callback) {
    // 直接使用 filter 函數來過濾參數
    return filter.call(elements, callback)
  }
關於 filter函數 詳細內容我在上篇博文已經解釋了,請對照 [Zepto源碼二之輔助函數](http://blog.csdn.net/qq_17347575/article/details/78973466)閱讀

$.extend

通過源對象擴展目標對象的屬性,源對象屬性將覆蓋目標對象屬性。

function extend(target, source, deep) {
    // 對源對象進行遍歷
    for (key in source)
      // 如果是深度遍歷,那麼還要判斷該屬性是否是對象或者數組。
      // 在對象與數組的情況要深層遞歸遍歷
      if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
        // 先判斷是對象還是數組,根據情況創建,方便後期賦值
        if (isPlainObject(source[key]) && !isPlainObject(target[key]))
          target[key] = {}
        if (isArray(source[key]) && !isArray(target[key]))
          target[key] = []

        // 遞歸調用
        extend(target[key], source[key], deep)
      }
      // 簡單的把 源對象的屬性值賦值給 目標對象。如果是深度遍歷的情況,那說明已經遍歷到最深的一層了
      // 如果是非深度遍歷,那就表示是最外層複製
      // 過濾了undefined 。且都是按引用賦值
      else if (source[key] !== undefined) target[key] = source[key]
  }

  $.extend = function (target) {
    var deep, args = slice.call(arguments, 1)

    // 從這個 if 判斷中可以看出,$.extend的兩種調用方式
    // $.extend(deep,target,source)
    // $.extend(target,source,deep)
    if (typeof target == 'boolean') {
      deep = target
      target = args.shift()
    }

    // 使用 forEach 方法來調用匿名函數
    // 匿名函數的具體職責是調用 extend 方法
    args.forEach(function (arg) { extend(target, arg, deep) })
    return target
  }
參考資料 Zepto 1.2.0 中文版API手冊
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章