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有关的源码。

猜你喜欢

转载自blog.csdn.net/qq_26626113/article/details/74784329