Zepto.js 之一步一步看源碼(二)

上文我們說到的zepto的結構,這次我們就看一下zepto如何封裝我們常用的方法的。通過學習別人封裝的方法,對自己也是一種提升

首先,我們所有返回的dom對象,所有的方法都封裝在了源碼中的$.fn中,dom對象是通過原型繼承來實現繼承$.fn中的方法,我們看一些我們常用的方法是如何封裝的

map: function(fn){
     //這裏要通過$封裝一下,這樣才能繼續調用後面的方法,實現連綴功能。
      return $(
        $.map(this, 
          function(el, i){ return fn.call(el, i, el) }
        )
      )

我麼可以看出來,在$.fn中的map方法實際上是調用了$.map方法,下面是$.map方法

$.map = function(elements, callback){
    var value, values = [], i, key
    if (likeArray(elements))
      for (i = 0; i < elements.length; 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)
      }
    return flatten(values)
  }

我們平時是這麼調用map的

array.map(function(idnex,val){
    //之所以這裏我們的順序是index,val,arr
    //其實就是因爲在$.map中我們在call裏傳的是就是index,val
    //有經驗的人應該知道 return this 返回的是val。這是因爲call的原因,一會細說
    return val;
})
function(el, i){ return fn.call(el, i, el) }

有人可能覺得這個call不是多餘的麼,根據代碼來看fn(i,el)也OK也能實現功能啊,這樣寫的確可以實現,但是之所以用call是因爲,這樣我們就可以在回調中使用this,你可以試着吧上面的源碼改掉,你會發現this指向的是window,這樣非常不友好。

再看下each函數

each: function(callback){     
        emptyArray.every.call(this, function(el, idx){
        return callback.call(el, idx, el) !== false
      })
      return this
    },

each是這裏面能代表大多數的例子,很簡單,就是使用call來調用原生方法,就是在原生方法上進行了一層封裝而已。因爲every方法並不影響回調函數內的執行。所以調用原生的every來實現each功能。

在源碼中很多方法在內部引用了each和map方法,所以還是有必要把這兩個方法搞明白的。

還有一些平時用到的插件小方法,都可以在這裏拿,這樣就省去我們因爲1-2個方法就去引入庫的問題,我們完全可以自己寫~~

比如看對象是否是空的

$.isEmptyObject = function(obj) {
    var name
    for (name in obj) return false
    return true
  }

for in循環連原型上的也一併遍歷,所以能確定這是否是個空對象。

鑑別數據類型

function type(obj) {
    return obj == null ? 
           String(obj) :  // null undefined
           class2type[toString.call(obj)] || "object" 
  }
  $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase()

function isFunction(value) { return type(value) == "function" }

這裏面很多例如toString和slice大家可能覺得前面少一些,其實zepto在前面已經定義了這些基本變量了,
emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter toString = class2type.toString

順帶介紹下toString,借用別人的

Object.prototype.toString.call(null);//”[object Null]”
Object.prototype.toString.call(undefined);//”[object Undefined]”
Object.prototype.toString.call(“abc”);//”[object String]”
Object.prototype.toString.call(123);//”[object Number]”
Object.prototype.toString.call(true);//”[object Boolean]”
2.判斷原生引用類型:
函數類型
Function fn(){console.log(“test”);}
Object.prototype.toString.call(fn);//”[object Function]”
日期類型
var date = new Date();
Object.prototype.toString.call(date);//”[object Date]”
數組類型
var arr = [1,2,3];
Object.prototype.toString.call(arr);//”[object Array]”

源碼中還有很多小插件,大家可以自己拿到源碼看看,都不是很難喲~~,以後再看看關於dom有關的源碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章