讀zepto核心源碼學習JS筆記(3)--zepto.init()

上篇已經講解了zepto.init()的幾種狀況,這篇就繼續記錄這幾種狀況下的具體分析.css

1. 首先是第一種狀況,selector爲空

既然是反向分析,那咱們先看看這句話的代碼;html

if (!selector) return zepto.Z()java

這裏的返回值爲zepto.Z();那咱們繼續往上找zepto.Z()函數node

zepto.Z = function(dom, selector) {
  return new Z(dom, selector)
}

這個函數仍然擁有一個返回值,Z函數的實例,一樣的道理,咱們繼續去找Z() ;正則表達式

function Z(dom, selector) {
  var i, len = dom ? dom.length : 0
  for (i = 0; i < len; i++) this[i] = dom[i]
  this.length = len
  this.selector = selector || ''
}

根據以上代碼能夠分析出,當沒有參數時,會獲得一個length:0,selector:''的對象.
數組

2. 當selector爲字符串的時候,又分爲三種狀況;

一樣的,咱們先看看這句話的代碼dom

else if (typeof selector == 'string') {
    selector = selector.trim()
}
  • 第一種,當selector爲html片斷
if (selector[0] == '<' && fragmentRE.test(selector))
      dom = zepto.fragment(selector, RegExp.$1, context), selector = null

這裏有兩個知識點:
1 fragmentRE.test(selector)函數

這裏的fragmentRE是Zepto函數在以前定義的一段正則;
```java
//<div>erfwef</div>  取出<div>
fragmentRE = /^\s*<(\w+|!)[^>]*>/,
```

2 zepto.fragment(selector, RegExp.$1, context)
* RegExp.$1
RegExp.$1爲RegExp的一個屬性,指的是與正則表達式匹配的第一個 子匹配(以括號爲標誌)字符串;
例子:
java var r= /^(\d{4})-(\d{1,2})-(\d{1,2})$/; r.exec('1985-10-15'); s1=RegExp.$1; s2=RegExp.$2; s3=RegExp.$3; alert(s1+" "+s2+" "+s3)//結果爲1985 10 15
* zepto.fragment()函數this

```java
//對應上面的代碼,這裏第一個參數是selector,就是咱們在寫代碼時的$('xxx')中的xxx,name爲RegExp.$1,即正則匹配的第一個()裏的東西,就是標籤元素,例如 div p  h1等,properties爲執行環境.
zepto.fragment = function(html, name, properties) {
      var dom, nodes, container
      // singleTagRE仍爲以前定義的變量,singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, 匹配值以下截圖
      //如html傳入值爲<p></p>,匹配singleTagRE,則建立<p></p>,並調用$('<p></p>')
      if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))
      //若是不匹配
      if (!dom) {
        //這是一段修復代碼,將<div/>之類的不正常的代碼修復成<div></div>;具體的下面再講解
        if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
        //若是沒有標籤名,,給他一個標籤,fragmentRE = /^\s*<(\w+|!)[^>]*>/,
        if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
        //containers = {tr': document.createElement('tbody'),tbody': table, 'thead': table, 'tfoot': table,td': tableRow, 'th': tableRow,'*': document.createElement('div')},
        //若是name值不在container範圍內,則標籤名爲div
        if (!(name in containers)) name = '*'
        //建立容器
        container = containers[name]
        //把html片斷放入到容器中
        container.innerHTML = '' + html
        //這裏調用了$.each();一會再詳細講解,這裏是涉及到哪一個函數我就去解析哪一個函數,雖然看起來比較亂,可是符合我本身的邏輯線路.
        //emptyArray = [], slice = emptyArray.slice,因此這裏的slice.call即爲Array.prototype.slice.call(),能將具備length屬性的對象轉成數組;
        dom = $.each(slice.call(container.childNodes), function(){
        //刪除
          container.removeChild(this)
        })
      }
      if (isPlainObject(properties)) {
        nodes = $(dom)
        $.each(properties, function(key, value) {
          if (methodAttributes.indexOf(key) > -1) nodes[key](value)
          else nodes.attr(key, value)
        })
      }
      return dom

}
```prototype

以上代碼出現了singleTagRE

  • singleTagRE

  • tagExpanderRE

  • fragmentRE

  • 第二種 當context有值
else if (context !== undefined) return $(context).find(selector)

這裏涉及到一個方法find,是$.fn中的方法,以後作統一分析;

  • 第三種 selector爲普通選擇器
else dom = zepto.qsa(document, selector)
zepto.qsa = function(element, selector){
        var found,
        //判斷是否是ID
        maybeID = selector[0] == '#',
        //判斷是否是css
        maybeClass = !maybeID && selector[0] == '.',
        //看是否是class和id名,若是是,將'#'或者'.'去除,而後賦值給nameOnlt;
        //不然,直接將值賦值;
        nameOnly = maybeID || maybeClass ? selector.slice(1) : selector,
        //simpleSelectorRE = /^[\w-]*$/,
        //匹配字母數字下劃線和減號的組合;
        isSimple = simpleSelectorRE.test(nameOnly)
        //若是有內置getElementById方法,而且是id名;
    return (element.getElementById && isSimple && maybeID) ?
        //則返回element.getElementByID(nameOnly)
      ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :
      //反之的話,再作一次判斷
      //若element不爲元素節點,document,DocumentFragment時;爲空,
      (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :
      //不然,將節點轉換成數組;
      slice.call(
      //這裏是一個三元運算符裏套着另外一個三元運算符;
        isSimple && !maybeID && element.getElementsByClassName ?
        //當爲class,則調用element.getElementsByClassName(nameOnly) 
              maybeClass ? element.getElementsByClassName(nameOnly) :
                //不然調用tagName;
              element.getElementsByTagName(selector) :
       //這個不然是最外層的判斷;
          element.querySelectorAll(selector)
      )
  }

3. 當傳入的值爲函數時,則在dom加載後執行它;

else if (isFunction(selector)) return $(document).ready(selector)

4. 若是selector爲Z的實例對象.則返回他本身;

else if (zepto.isZ(selector)) return selector

5. 最後,又分爲5種狀況;

  • 若是selector爲數組;
    java // if (isArray(selector)) dom = compact(selector)
    這裏用到了一個compact方法;
    java //這裏調用了一個filter方法,是在$.fn內,之後統一分析; //這個函數是去除數組中的null和undefined; function compact(array) { return filter.call(array, function(item){ return item != null }) }
    因此當爲數組的時候,去除數組中的null和undefined;

  • selector爲對象
    java else if (isObject(selector)) dom = [selector], selector = null
    若是selector爲對象,將對象變爲一個數組;
  • selector爲html片斷;則將其轉換成dom
    java else if (fragmentRE.test(selector)) dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
  • 有context的時候

    else if (context !== undefined) return $(context).find(selector)
  • 沒有context
    java else dom = zepto.qsa(document, selector)

相關文章
相關標籤/搜索