zepto学习之路--源代码提取

   最近在看zepto的源代码,把一些有用的函数摘出来,看看zepto是怎么实现的,自己做的时候也可以用。说实话,zepto的实现有一些看起来还是很晦涩的,可能是自己的水平不够,看不透作者的真正的意图。

1、zepto的正则总结:

//HTML代码片断的正则
    fragmentRE = /^\s*<(\w+|!)[^>]*>/
//匹配非单独一个闭合标签的标签,类似将<div></div>写成了<div/>
    tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig
//根节点
    rootNodeRE = /^(?:body|html)$/i
//class选择器的正则
    classSelectorRE = /^\.([\w-]+)$/,
 //id选择器的正则
    idSelectorRE = /^#([\w-]*)$/,
//DOM标签正则
    tagSelectorRE = /^[\w-]+$/,

2、zepto工具函数总结(我的意思只是我感觉比较有用的哈):

 

 //判断一个元素是否匹配给定的选择器
//这里作者的实现我觉得有点小问题,其思想是在其父元素中按照selecor找出匹配的元素再indexOf判断是否存在,但是,如果selector是这样的呢“body div .a”,在其父元素中能匹配到body吗?我觉得还不如直接在document下匹配,欢迎拍砖。可能是我笨吧,或者zepto的qsa函数比较高级。
  zepto.matches = function(element, selector) {
    if (!element || element.nodeType !== 1) return false
    //引用浏览器提供的MatchesSelector方法
    var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.matchesSelector
    if (matchesSelector) return matchesSelector.call(element, selector);
    //如果浏览器不支持MatchesSelector方法,则将节点放入一个临时div节点,
    //再通过selector来查找这个div下的节点集,再判断给定的element是否在节点集中,如果在,则返回一个非零(即非false)的数字
    // fall back to performing a selector:
    var match, parent = element.parentNode,temp = !parent
    //当element没有父节点,那么将其插入到一个临时的div里面
    if (temp)(parent = tempParent).appendChild(element)
    //将parent作为上下文,来查找selector的匹配结果,并获取element在结果集的索引,不存在时为-1,再通过~-1转成0,存在时返回一个非零的值
    match = ~zepto.qsa(parent, selector).indexOf(element)
    //将插入的节点删掉
    temp && tempParent.removeChild(element)
    return match
  }

  接下来就有个大问题了,是zepto的类型判断部分,求解答:

//问题在这里,下面的type函数中,很明显有问题啊,class2type[toString.call(obj)]我感觉不对啊,我感觉应该是toString.call(obj).slice(8,-1);待我去知乎上问下,再分享给大家。
//好吧,我承认自己太急躁了原来还有下面这么一段,
  $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
  class2type[ "[object " + name + "]" ] = name.toLowerCase()
  })

var class2type={},toString=class2type.toString;
function type(obj) {
    //obj为null或者undefined时,直接返回'null'或'undefined'
    return obj == null ? String(obj) : class2type[toString.call(obj)] || "object"
  }

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

  function isWindow(obj) {
    return obj != null && obj == obj.window
  }

  function isDocument(obj) {
    return obj != null && obj.nodeType == obj.DOCUMENT_NODE
  }

  function isObject(obj) {
    return type(obj) == "object"
  }
  //对于通过字面量定义的对象和new Object的对象返回true,new Object时传参数的返回false
  //可参考http://snandy.iteye.com/blog/663245

  function isPlainObject(obj) {
    return isObject(obj) && !isWindow(obj) && obj.__proto__ == Object.prototype
  }

  function isArray(value) {
    return value instanceof Array
  }
  //类数组,比如nodeList,这个只是做最简单的判断,如果给一个对象定义一个值为数据的length属性,它同样会返回true

  function likeArray(obj) {
    return typeof obj.length == 'number'
  }

 3、数组操作

//清除给定的参数中的null或undefined,注意0==null,'' == null为false
//这个很赞,用filter
  function compact(array) {
    return filter.call(array, function(item) {
      return item != null
    })
  }
  //类似得到一个数组的副本,拷贝数组a就return a.concat([]);很赞

  function flatten(array) {
    return array.length > 0 ? $.fn.concat.apply([], array) : array
  }

//数组去重,如果该条数据在数组中的位置与循环的索引值不相同,则说明数组中有与其相同的值

//数组去重的方法有很多,但作者的这个方法真心赞,让我折服了,即短又高效!
uniq = function(array) {
return filter.call(array, function(item, idx) {
return array.indexOf(item) == idx
})
}

 4、字符串操作

//将字符串转成驼峰式的格式
  camelize = function(str) {
    return str.replace(/-+(.)?/g, function(match, chr) {
      return chr ? chr.toUpperCase() : ''
    })
  }
  //将字符串格式化成-拼接的形式,一般用在样式属性上,比如border-width
    //这个写的太赞了,真的是每一句都很赞,由衷的佩服。
  function dasherize(str) {
    return str.replace(/::/g, '/') //将::替换成/
    .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') //在大小写字符之间插入_,大写在前,比如AAAbb,得到AA_Abb
    .replace(/([a-z\d])([A-Z])/g, '$1_$2') //在大小写字符之间插入_,小写或数字在前,比如bbbAaa,得到bbb_Aaa
    .replace(/_/g, '-') //将_替换成-
    .toLowerCase() //转成小写
  }

  

posted @ 2015-04-06 21:11  低调的大白兔  阅读(572)  评论(0编辑  收藏  举报