读zepto.js源码的一些笔记

May 19, 2015

577

这两天把zepto.js源码重新读了一遍,对其中的一些要点做了笔记(zepto版本号:1.1.6)。

Zepto代码主要分为两部分,一部分是Zepto核心,包括Zepto集合的初始化以及常见的函数,另一部分为插件模式,包括事件绑定、ajax等。

先看一下Zepto的基本结构,简化后代码如下:

var Zepto = (function() {
  var $, zepto = {}

  //这里主要是绑定原型,返回zepto集合
  zepto.Z = function(dom, selector) {
    dom = dom || [] //对象数组
    dom.__proto__ = $.fn //将dom的原型指向$.fn
    dom.selector = selector || ''
    return dom
  }

  //判断是否为Zepto集合
  zepto.isZ = function(object) {
    return object instanceof zepto.Z
  }

  //初始化
  zepto.init = function(selector, context) {
    return zepto.Z(dom, selector)
  }

  //创建
  $ = function(selector, context){
    return zepto.init(selector, context)
  }

  //复制属性,这个函数主要用于扩展插件
  $.extend = function(target){
    return target
  }

  //原型
  $.fn = {}

  zepto.Z.prototype = $.fn

  $.zepto = zepto

  return $
}());

window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)

这里面有疑问的是__proto__属性,这个属性指向对象的原型,通过这个属性,zepto对象无需采用new就可以访问到原型中的方法,有些浏览器如IE10以下并没有__proto__属性,zepto是如何处理的呢?

zepto通过插件模式重写了zepto.Z和zepto.isZ函数,插件代码如下:

;(function($){
  // __proto__ doesn't exist on IE<11, so redefine
  // the Z function to use object extension instead
  if (!('__proto__' in {})) {
    $.extend($.zepto, {
      Z: function(dom, selector){
        dom = dom || []
        $.extend(dom, $.fn)
        dom.selector = selector || ''
        dom.__Z = true
        return dom
      },
      // this is a kludge but works
      isZ: function(object){
        return $.type(object) === 'array' && '__Z' in object
      }
    })
  }

  // getComputedStyle shouldn't freak out when called
  // without a valid element as argument
  try {
    getComputedStyle(undefined)
  } catch(e) {
    var nativeGetComputedStyle = getComputedStyle;
    window.getComputedStyle = function(element){
      try {
        return nativeGetComputedStyle(element)
      } catch(e) {
        return null
      }
    }
  }
})(Zepto)

在这里,__proto__采用extend重写,直接将$.fn中的属性复制到zepto集合中,这样子,无需new实例化便可访问$.fn中的属性。

顺便提一下getComputedStyle这个函数,getComputedStyle返回的样式是一个CSSStyleDeclaration 对象,第一个参数必须是Element对象(如果不是Element节点,如 #text Node 文字类型,将会抛出错误) 。zepto重写该函数主要是提前捕获异常,防止浏览器抛出错误中断代码执行。

以下主要是记录zepto对数组的操作:

  1. 去重复值,代码如下:
var uniq = function(array){ 
  return [].filter.call(array, function(item, idx){ 
    return array.indexOf(item) == idx }
  )
}

这个函数直接利用了数组的filter过滤掉重复的值。

  1. 数组扁平化,代码如下:
function flatten(array) { 
  return array.length > 0 ? [].concat.apply([], array) : array 
}

这个函数直接利用数组concat方法以及apply函数的特性,但只能处理类似[1,[2,3],[4]]的扁平化,无法处理[1,[2,[3,[4]]]],自己重写了一个数组扁平化的函数,代码如下:

//out参数默认不传,主要用于存取结果
function flatten(array, out) {
  out = out || [];

  for (var i = 0, length = array.length; i < length; i++) {
    if (Array.isArray(array[i])) {
      flatten(array[i], out);
    } else {
      out.push(array[i]);
    }
  }

  return out;
}

JavaScript 」相关文章

Wen's Blog

文章归档 » 文章标签 » 博主:吴文伟,Web开发爱好者,专注于前端开发,该博客用于记录和分享平时遇到的一些问题以及知识。

订阅

联系方式

链接